Revision 01d91d195d1b862eb54c8dc8dbf7b41635f7e876 authored by Marek Gagolewski on 13 November 2023, 14:10:02 UTC, committed by cran-robot on 13 November 2023, 15:30:42 UTC
1 parent ea1271d
random.R
# kate: default-dictionary en_US
## This file is part of the 'stringi' package for R.
## Copyright (c) 2013-2023, Marek Gagolewski <https://www.gagolewski.com/>
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are met:
##
## 1. Redistributions of source code must retain the above copyright notice,
## this list of conditions and the following disclaimer.
##
## 2. Redistributions in binary form must reproduce the above copyright notice,
## this list of conditions and the following disclaimer in the documentation
## and/or other materials provided with the distribution.
##
## 3. Neither the name of the copyright holder nor the names of its
## contributors may be used to endorse or promote products derived from
## this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
## BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
## FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
## OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
## WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
## OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
## EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#' @title
#' Randomly Shuffle Code Points in Each String
#'
#' @description
#' Generates a (pseudo)random permutation of the code points
#' in each string.
#'
#' @details
#' This operation may result in non-Unicode-normalized
#' strings and may give peculiar outputs in case of bidirectional strings.
#'
#' See also \code{\link{stri_reverse}} for reversing the order of code points.
#'
#' @param str character vector
#'
#' @return Returns a character vector.
#'
#' @examples
#' stri_rand_shuffle(c('abcdefghi', '0123456789'))
#' # you can do better than this with stri_rand_strings:
#' stri_rand_shuffle(rep(stri_paste(letters, collapse=''), 10))
#'
#' @family random
#' @export
stri_rand_shuffle <- function(str)
{
.Call(C_stri_rand_shuffle, str)
}
#' @title
#' Generate Random Strings
#'
#' @description
#' Generates (pseudo)random strings of desired lengths.
#'
#' @details
#' Vectorized over \code{length} and \code{pattern}.
#' If length of \code{length} or \code{pattern} is greater than \code{n},
#' then redundant elements are ignored. Otherwise,
#' these vectors are recycled if necessary.
#'
#' This operation may result in non-Unicode-normalized
#' strings and may give peculiar outputs for bidirectional strings.
#'
#' Sampling of code points from the set specified by \code{pattern}
#' is always done with replacement and each code point appears with equal
#' probability.
#'
#' @param n single integer, number of observations
#' @param length integer vector, desired string lengths
#' @param pattern character vector specifying character classes to draw
#' elements from, see \link{stringi-search-charclass}
#'
#' @return Returns a character vector.
#'
#' @examples
#' stri_rand_strings(5, 10) # 5 strings of length 10
#' stri_rand_strings(5, sample(1:10, 5, replace=TRUE)) # 5 strings of random lengths
#' stri_rand_strings(10, 5, '[\\p{script=latin}&\\p{Ll}]') # small letters from the Latin script
#'
#' # generate n random passwords of length in [8, 14]
#' # consisting of at least one digit, small and big ASCII letter:
#' n <- 10
#' stri_rand_shuffle(stri_paste(
#' stri_rand_strings(n, 1, '[0-9]'),
#' stri_rand_strings(n, 1, '[a-z]'),
#' stri_rand_strings(n, 1, '[A-Z]'),
#' stri_rand_strings(n, sample(5:11, 5, replace=TRUE), '[a-zA-Z0-9]')
#' ))
#'
#' @family random
#' @export
stri_rand_strings <- function(n, length, pattern = "[A-Za-z0-9]")
{
.Call(C_stri_rand_strings, n, length, pattern)
}
#' @title
#' A Lorem Ipsum Generator
#'
#' @description
#' Generates (pseudo)random \emph{lorem ipsum} text consisting
#' of a given number of text paragraphs.
#'
#' @details
#' \emph{Lorem ipsum} is a dummy text often used as a source
#' of data for string processing and displaying/lay-outing exercises.
#'
#' The current implementation is very simple:
#' words are selected randomly from a Zipf distribution
#' (based on a set of ca. 190 predefined Latin words).
#' The number of words per sentence and sentences per paragraph
#' follows a discretized, truncated normal distribution.
#' No Markov chain modeling, just i.i.d. word selection.
#'
#' @param n_paragraphs single integer, number of paragraphs to generate
#' @param start_lipsum single logical value; should the resulting
#' text start with \emph{Lorem ipsum dolor sit amet}?
#' @param nparagraphs [DEPRECATED] alias of \code{n_paragraphs}
#'
#' @return Returns a character vector of length \code{n_paragraphs}.
#'
#' @examples
#' cat(sapply(
#' stri_wrap(stri_rand_lipsum(10), 80, simplify=FALSE),
#' stri_flatten, collapse='\n'), sep='\n\n')
#' cat(stri_rand_lipsum(10), sep='\n\n')
#'
#' @family random
#' @export
stri_rand_lipsum <- function(n_paragraphs, start_lipsum = TRUE,
nparagraphs=n_paragraphs)
{
if (!missing(nparagraphs) && missing(n_paragraphs)) { # DEPRECATED
warning("The 'nparagraphs' argument in stri_rand_lipsum is a deprecated alias of 'n_paragraphs' and will be removed in a future release of 'stringi'.")
n_paragraphs <- nparagraphs
}
# Whoa! A pure R function in stringi :)
# Version 0.3-1 (Marek Gagolewski, 2014-10-16)
n_paragraphs <- as.integer(n_paragraphs)
stopifnot(is.finite(n_paragraphs), n_paragraphs >= 1)
start_lipsum <- identical(start_lipsum, TRUE)
rwords <- function(n) {
# generate n random words
words <- c("SED", "IN", "UT", "ET", "AC", "EU", "NON", "NEC", "AMET", "SIT",
"VEL", "AT", "MAURIS", "A", "VITAE", "EGET", "QUIS", "NUNC", "NULLA",
"ID", "VESTIBULUM", "PELLENTESQUE", "TINCIDUNT", "ALIQUAM", "IPSUM",
"DONEC", "TURPIS", "LIGULA", "EGESTAS", "NIBH", "SAPIEN", "ANTE", "NISL",
"VELIT", "ERAT", "EROS", "LEO", "MAGNA", "JUSTO", "ENIM", "MI", "PURUS",
"EST", "LACUS", "LOREM", "QUAM", "DIAM", "RISUS", "DOLOR", "SEM", "AUGUE",
"NEQUE", "TEMPOR", "DUI", "ARCU", "METUS", "TORTOR", "URNA", "LIBERO",
"PHARETRA", "TEMPUS", "FAUCIBUS", "LECTUS", "SUSPENDISSE", "FELIS", "ODIO",
"ORCI", "VARIUS", "MASSA", "TELLUS", "VOLUTPAT", "BLANDIT", "INTERDUM",
"LOBORTIS", "MAXIMUS", "NISI", "LUCTUS", "PORTTITOR", "AUCTOR", "ELEMENTUM",
"EX", "MAECENAS", "MALESUADA", "TRISTIQUE", "ULLAMCORPER", "ULTRICES",
"NULLAM", "CONSEQUAT", "LACINIA", "PHASELLUS", "ACCUMSAN", "DAPIBUS",
"ELEIFEND", "COMMODO", "DUIS", "EFFICITUR", "ELIT", "IMPERDIET", "AENEAN",
"IACULIS", "NAM", "CONSECTETUR", "FERMENTUM", "PORTA", "SCELERISQUE",
"SODALES", "FEUGIAT", "LAOREET", "VULPUTATE", "DICTUM", "QUISQUE", "FACILISIS",
"FINIBUS", "ORNARE", "PULVINAR", "RHONCUS", "CONDIMENTUM", "MOLLIS",
"PRETIUM", "ALIQUET", "CONGUE", "POSUERE", "SUSCIPIT", "ULTRICIES", "CURABITUR",
"GRAVIDA", "MATTIS", "VIVERRA", "CURSUS", "EUISMOD", "RUTRUM", "VENENATIS",
"CONVALLIS", "PROIN", "VEHICULA", "PLACERAT", "SAGITTIS", "CRAS", "INTEGER",
"MORBI", "VIVAMUS", "PRAESENT", "BIBENDUM", "MOLESTIE", "SEMPER", "FRINGILLA",
"FUSCE", "DIGNISSIM", "ETIAM", "HENDRERIT", "SOLLICITUDIN", "PER", "FAMES",
"POTENTI", "AD", "APTENT", "CLASS", "CONUBIA", "HIMENAEOS", "INCEPTOS",
"LITORA", "NOSTRA", "SOCIOSQU", "TACITI", "TORQUENT", "HABITANT", "NETUS",
"SENECTUS", "PRIMIS", "CUM", "DIS", "MAGNIS", "MONTES", "MUS", "NASCETUR",
"NATOQUE", "PARTURIENT", "PENATIBUS", "RIDICULUS", "SOCIIS", "ADIPISCING",
"FACILISI", "CUBILIA", "CURAE", "DICTUMST", "HABITASSE", "HAC", "PLATEA")
# Zipf distribution
dzipf <- function(k, N, s) 1/k^s/sum(1/(1:N)^s)
pzipf.y <- c(0, cumsum(dzipf(1:length(words), length(words), 0.5)))
robs <- findInterval(runif(n), pzipf.y)
words[robs]
}
rtruncnorm <- function(n, a, b, mu, sd) {
# truncated discretized normal distribution
x <- round(rnorm(n, mu, sd))
while (any(x < a | x > b)) x[x < a | x > b] <- round(rnorm(sum(x < a | x >
b), mu, sd))
x
}
sent_para <- rtruncnorm(n_paragraphs, 7, 20, 11, 3)
word_sent <- lapply(sent_para, function(numsent) rtruncnorm(numsent, 2, Inf,
8, 3))
totwords <- sum(unlist(word_sent))
words <- rwords(totwords)
seps <- sample(c(" ", ", "), replace = TRUE, size = totwords, prob = c(0.9, 0.1))
seps[cumsum(unlist(word_sent))] <- sample(c(". ", "? ", "! "), size = length(unlist(word_sent)),
replace = TRUE, prob = c(0.95, 0.025, 0.025)) # end of sentence
seps[cumsum(sapply(word_sent, sum))] <- ".\n" # end of para
seps[totwords] <- "." # very last sentence in very last para
if (start_lipsum) {
words <- c("LOREM", "IPSUM", "DOLOR", "SIT", "AMET", words)
seps <- c(" ", " ", " ", " ", ", ", seps)
}
ret <- stri_split_charclass(stri_paste(words, seps, collapse = ""), "[\\n]")[[1]]
ret <- stri_trans_totitle(ret, opts_brkiter = stri_opts_brkiter(type = "sentence"))
ret
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...