Extract punctuation from books with R

A screenshot of the R console in RStudio showing a large number of printed punctuation characters with linebreaks every 70 characters and with each punctuation mark coloured differently.

The start of ‘Moby Dick’ by Herman Melville

tl;dr

I wrote an R function to extract only the punctuation marks from a provided text. It prints prettily to the console, but you can also take a character vector away for further analysis.

Punct rock

A few years ago Adam J Calhoun did a small but really neat thing: extracted and presented only the punctuation from some books. It appeared again recently in my Twitter timeline.

I love the aesthetic of the neatly printed characters, but it also tells us something (obvious?) about writing styles.

Long story short: old-timey folk often wrote convoluted sentences; literature and essays from a hundred or more years ago are especially rich with semi-colons, commas, more commas and of course, as the audience is well-aware, even more commas, which to modern eyes can be a little tiring; certainly it’s a style that is out of fashion, but was pretty hip for, let’s say, Herman Melville, when writing his behemoth of a novel, Moby Dick; Or, The Whale.

Whereas Hemingway was terse.

You’ve been punct

So I wrote a small, opinionated R function called extract_punct() that grabs the punctuation characters for a given text.

Someone has probably done this in R before. I saw that Julia Silge wrote a post on quantifying punctuation like Calhoun’s original, but it doesn’t involve printing the characters.

The purpose of this post is just to show how to do the extraction and print it nicely to the console, though the function allows you to take away a character vector for further analysis.

Functuation

Below is the definition for extract_punct(). You supply your content to text, and then you set the arguments:

  • sort = FALSE to return the punctuation in the order it appears in the text, or TRUE to order it ‘alphabetically’
  • vec_only = TRUE to early-return the punctuation characters as a vector for you to do with as you please
  • vec_only = FALSE to print the results to the console with cat()
  • width to decide where the line breaks will go in the printed output (defaults to 80)
  • colour = TRUE to have each punctuation character returned in colour thanks to the {crayon} package by Gábor Csárdi1, or FALSE to return without colour
extract_punct <- function(text,              # input text
                          sort = FALSE,      # order the characters?
                          vec_only = FALSE,  # return as char vector?
                          width = 80,        # width of output
                          colour = TRUE) {   # colour output?
  
  # Extract punctuation with regular expression
  punct_rx  <- "[\\.,:;!?\"\'\\()]"
  matches   <- regexpr(punct_rx, text)
  punct_vec <- regmatches(text, matches)
  
  # Sort alphabetically?
  if (sort) punct_vec <- punct_vec[order(punct_vec)]
  
  # Early return of character vector
  if (vec_only) return(punct_vec)
  
  # Colour the characters
  punct_vec <- sapply(
    punct_vec, switch,
    "."  = crayon::blue("."),
    "!"  = crayon::blue("!"),
    "?"  = crayon::blue("?"),
    ","  = crayon::yellow(","),
    ";"  = crayon::yellow(";"),
    ":"  = crayon::yellow(":"),
    "\"" = crayon::red("\""),
    "'"  = crayon::red("'"),
    "("  = crayon::silver("("),
    ")"  = crayon::silver(")")
  )
  
  # Print without colour
  if (!is.null(width) & !colour) {
    cat(names(punct_vec), sep = "", fill = width)
  }
  
  # Convoluted colour printing, requires flattening a matrix
  if (!is.null(width) & colour) {
    div_size <- length(punct_vec) %/% width * width
    mat_flat <- c(rbind("\n", matrix(punct_vec[1:div_size], nrow = width)))
    leftover <- c("\n", punct_vec[div_size:length(punct_vec)])
    cat(mat_flat[2:length(mat_flat)], leftover, sep = "")
  }
  
}

There’s no defensive programming or testing here; this is just for fun for the purposes of this blog post. Maybe it’ll work on your machine?

I decided to colour by ‘type’ of mark: terminal (period, exclamation and question), ‘continuing’ marks (comma, semi-colon and colon), parenthetical (open and close) and quote signifiers (quotation marks and apostrophes, recognising that apostrophes are more likely to be used for contractions).

There were a couple of technical annoyances to deal with in the function definition; let me know what you would improve.2

{gutenbergr}, dead ahead!

Let’s inspect the punctuation from some books on Project Gutenberg, ‘a volunteer effort to digitize, archive, and distribute literary works’.

Helpfully, we can interact with Project Gutenberg’s library via the {gutenbergr} package by David Robinson.3

library(gutenbergr)
library(dplyr, warn.conflicts = FALSE)
library(stringr)

sample_n(gutenberg_metadata, 5) %>% select(1:3)
# A tibble: 5 × 3
  gutenberg_id title                                        author              
         <int> <chr>                                        <chr>               
1        16376 "Browning's Shorter Poems"                   Browning, Robert    
2        39090 "Travelers Five Along Life's Highway\r\nJim… Johnston, Annie F. …
3        16806 "Rosmersholma: Nelinäytöksinen näytelmä"     Ibsen, Henrik       
4        25684 "A World Called Crimson"                     Granger, Darius John
5         2430 "Romantic Ballads, Translated from the Dani… <NA>                

You could filter for a particular author or title, like Franz Kafka.

gutenberg_metadata %>% 
  filter(str_detect(author, "Kafka")) %>%
  select(1:3) %>%
  slice(1:5)
# A tibble: 5 × 3
  gutenberg_id title                    author      
         <int> <chr>                    <chr>       
1         5200 Metamorphosis            Kafka, Franz
2         7849 The Trial                Kafka, Franz
3        16304 Der Heizer: Ein Fragment Kafka, Franz
4        19638 Auf der Galerie          Kafka, Franz
5        20045 Großer Lärm              Kafka, Franz

I’ve chosen Edwin A Abbott’s Flatland (1884) as our example text. It’s relatively short, so we can get the gist of the output from extract_punct() without printing hundreds of lines. Also it’s a really fun little book that blew my mind.4

You can get a Gutenberg book by finding its ‘Gutenberg ID’ to input into extract_punct()? One way is to look at the URL for a given book on the Project Gutenberg website, another is to search the gutenberg_metadata()5 dataframe. I’ll also load {dplyr} and {stringr} for wrangling.

id <- gutenberg_works() %>% 
  filter(str_detect(title, "^Flatland: A Romance of Many Dimensions$")) %>%
  pull(gutenberg_id)

book <- gutenberg_download(id, verbose = FALSE)

book %>% filter(!is.na(text)) %>% sample_n(5) %>% select(text)
# A tibble: 5 × 1
  text                                                                     
  <chr>                                                                    
1 ""                                                                       
2 "The Southward attraction in our country is so slight that even to a"    
3 "straight line; and it was added or implied, that it is consequently"    
4 "the vain belief that conduct depends upon will, effort, training,"      
5 "imprisonment, but added his satisfaction that, unless some mention were"

Right so, we can pass the text to the extract_punct() function to return all the punctuation in the order it appears, with linebreak every 70 characters so the text fits the width of this blog.

extract_punct(book$text, width = 70, colour = FALSE)
..,,.,,,,.".,",..,.;,,(),(),,,,..;,;(..,(),.,.;;,.:.,.,,,;.;.),,.,..,,
,,.,,,.:,,,?.,,,;;!.,,;;,(,(,:,,,.,.,.;,.....,(.(;.;..(),,,,,;,.;,,,.(
.,.,,(.(,,,..,,.,,,,,,,,.,,,.,,).,,.!,!,,..,;,,;.,;,,,;..",.;;,,.,,,,.
,....,,.,,;,..;;;;?,,,,,.:.;"..,.,,,,;,;.,.,;.,,.,.,,..,,.,,,"."..,,,,
,,.,,,.;,,.,..,',..;;,..,;.;,,.,,,;.;.'',,',,;.;.,,.,,,,'.,,,.;,,,,,,.
.,,,.,,,,,.",."",""""",.,,,.;,..;.,...,,...,.!,,,,,.,,,,'.,,,..,,,,,,?
,.,,..,(,,,,.,,,,.;,.,,.;,,.,,,,,.,,..;.,,,..;:.,".;.,,,..,;.,,;,...,?
,,((.(,;,',((,:,.,...,,.,,,,,,()..,,,,,,,.,.,,,.,.,,.,,,,",.,.",,,"",.
(;,,...",;,,,...,,.,,,,;,,,.,.,;;,...,,.,..,,..;,;;,?,,,,.,:,:?.;'';,,
.:.,,,.,,,;,;,,!,,.;.,?'???!,!,,.(,.,:.,.;,,.,.,;,,.;,,,,?.,.,,,.,.;;.
.,...;.,..",...,(,,";,.,,,..;;.,;,,;,,,''.;..,;,..,,,.,,,,,"",,,,.,,,,
,(),,;.,,,,..,,.,,,(.,,(;(((,;,.;;,...,;,,.,,....,,,.,,.,,,.,.'.,.;.,.
,.;,...;,,.,,(.,;,,...,,.;.;,.,.;,.,.,.,,,,,.,.,.,;..;;,,,.,,,,,.",;,,
;,.,',..,,,.;'...,,.;,,..,.,..,,;.,..,..,,;,,;,;,,,,.,,:,.,,,,.,,.;,.:
,.,.,,.,.,.,,.';,,.;,.,,,,,...,,..,;,,,,,,.,,,;,;,,;.,,,;;.,,.,??,.,,,
',;,,,,,'.;,;,,.,.,,,:,..,.;,,.,...,,;,;',,,.,;.,,.,,,,;.,,.,;..,.,,,,
,;,"",;:"'.,,,..;.,.",.,.(),.,;,,,.,,,,?".,;.;.:,,.,,,.,,;.;,,;...,,.,
..,,.,,;.(,,,,?",,...."..,.,."".,?";.;",.,,,.,,;,."?",?;.".,',..,;.,..
,,,.,,.?,;"",,,,".;,,,.,,,....,..",???,;.",",.,;,.",?,',,,:!,,,."..!!!
!;,.,,,,.",.,,'.".........,.....,?,,.?...,,,,,,.;,,,?.,,.,..,;,.?,,!.!
;,..:,,.;,,.;,...;),;.,,.,,,,,:,.;:;?.,,,.,,;,,,).",;';..;,.,.;,"?,.,.
,,.!';,.,.,.?.;"""'.".,",?";.,;,,,...;,),".,.,:..,,,,),,,,.,..,,...?.,
,,.?..,...;,.,...,...,..:,;...,.(",...,,,.,,..,.?.'..?.,,,,,,....,.,;.
.?...,,".:..,.".....,,,,,.,..,,,,,,,,..,;,..".."?..,.,,,,,,,.,.,,.,.,.
.,....,.?.....,..,..,,;..,,"'..,,.,...:.....".,.."?.,,;,?....,,"..,.,:
;,...,:...,,;.,.....,..,:,;....",;;,,.,,.,,,,,,?.'!,.,.,,.:.,....!".":
,.;;..,.,,.:;,,,,",.,,..',,...,.,,,.!,;.,.,,,,,',,,...,.,.,,.,:":.,..,
.,?.!,...,.?,,,.".,,,.,.:,,,,,,,,."..",.,.(,,,.!"",..,..,,,,,',,,,,.,.
..,.,..,.";,,.";..,,;,.".',.,,,,,:,,;,.!,.,;,,.,.";....?.,.,,.,,,,,,,,
.....,,..;?..,,,,,.......,;',.,,,,,,...,,,,,,,..?,?,?,,?,,?,?',,?,,:,,
.,,,,,?..(..,.,..,,(.;..,.,,,,,.,,.,,.,...,.!..,,..,,,.,,;,,..;,.;,,."
.,.,.,,,.";;,,".;,;;.,..;,,!",,",,,,"",,,:",,,.,,.,,!!,",':.,,,;.,,".,
,...,..,,,..,,..,;,,,,,,,.,?,;,.,,.,,.,,,.,,.,.,'.'.,.,,,;;',!!",",,,,
,;.,;.,;..,,,,,:,,;("..,,.,,.,;(.;,.?,.,,.,,;",",,,,,,.;,,.?,,.;,,,.;.
,,:.".)?,,,.,.,,.,.,,.;.,,,.,.,,,.,,..,;",;;,,,,,,,,,,,.,,,,,,((,),,."
'',,',',;",(,.;,,,,,,,),,'?.;".,((,,.?,.!,,'.(.;',..,,.(.(,;..,,,,",,.
;,,,,,..().

I passed colour = FALSE because the blog can’t render the colours. Set colour = TRUE to have the characters returned in your console with a different colour for each type of mark. That looks like this:

A screenshot of the R console in RStudio showing a large number of printed punctuation characters with linebreaks every 70 characters and with each punctuation mark coloured differently.

All punctuation from ‘Flatland’ by Edward A Abbott

For fun, we can also get the same output as before, but ordered by character.

extract_punct(book$text, sort = TRUE, width = 70, colour = FALSE)
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;::::::::::::::::::::::::::::::::::::::!!!!!!!!!!!!!!!!!!!!!
!!!!!!!???????????????????????????????????????????????????????????....
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
..........''''''''''''''''''''''''''''''''''''''''''''''""""""""""""""
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
""""""""""""""""""(((((((((((((((((((((((((((((((((((((((((((((())))))
)))))))))))

Full stop

So that’s the general gist.

Here’s a few more books from Project Gutenberg. Expand to see the punctuation for each one:

Pride and Prejudice by Jane Austen (1813)
extract_punct(
  gutenberg_download(1342, verbose = FALSE)$text,
  width = 70
)
,,,,..?.,..?.,.,;,;,.?.?!.?.!.?!,..,,.,,,.,,.,..,,,,;;..;,.,;....,..,,
.,.,..,.,.;...;..,,..,,,...,..,,.,.,,.,;,,.,;...;;,.,?,,.,,,..;?.,;.,.
,..,.,;.,.;,;..!,...,.;,;,..,.;.,,..,;,,.;.,.,;,.;..;,,;,..,,,,,,.,.,;
,,..;,..!,,,.,..,;.,,....,.,!;.,.!,,.?,,.,...,,.....,.;,.,...;.,,.;,;.
.,;..,,,,,!!!....,,,;,!!!.,..,,,,,..?.....!!...;.;,!.,,.;.;.,;,,.,;,,,
;,.;..,,,,,,;,,,...,,,,.,,.,...,.,..;;;,,,,...,.,..,,..;,,,,.;,.,.,,;.
,..;!..?,,?!.!,,.,,..,.,;.,..,,;....,,,.,,,,,,,,,,;,.....,,,..;,...,,.
;,,,.,;,,,.,;.,;.,.;.,.,,,.,.,,,,;,..,.,;,..,.,...;.;;,.,,..,.;.,,..;;
.,.,;,.;,.,,.,.?..,.,,,,,,?;..,,!!,,.,,,,.,,,,,,;,,.,;,,,..,,,..,...,,
.,,.,?.,.;.;;,,,...,,,..,.,;,,.,,?,,,..;.;!,..,..!.?.;,.,.,.,;,.,,,.,.
,.;,,.,;,;,.;....,..;,.,.,.,,,,,,.,.,.,,.,....,,,;.,;..;.,,,,,,,,...!.
,?,;,.!;.,,.,..,..,;.,,,.:,,...,,,,,.!.,.,;,.,,..,?,,.,;,.,..,.;,,,,,.
,,.,..;;..,...,.;,,.,.,,.,,;.,,;.,.,,.,,,.,...,,:,.,.,..;,;.,.,;.,..,!
,,,,.,...,..,,?,.,.,,.,,,,.,.;,.,,,;,.,,.,,.,;,,?.,,,;.,;.,.;;..,.,,.,
..!.,.,.;.,,.,;,.??.,!.!.,.!?,.,,...,.,,.;!.,;,,.,,..?.,.,,,.,,,;,,,,.
..,;,.;;,..,.,.,.,,..,.,;,,.;,.,...,..!,,,..,,,,,.,.,,,..,.,.!;...,.,.
;.,..,.,..;,,,,,;,.,.,.,,,....,.,,!.,.?,.;.,!.,!,,..,...,,!,.,.,.;....
,.,..,,.,;,.,,.;..,,...,.,...,.,,..,.,,,..,.,,,,.!...!!,..,...?.,,.?!,
;.,,,,..!...,.,..?;,,,,.,,?,.,..;.;,,,,..,.;,,.?,.,,,,,...,.,..,.,,,,,
?,;,.,.,,..,,.,,.,;,..,.,,,.,,.;,.,..,;,,?,.!.,,.,..,;;.,,.,,.,,,;.,,.
?!...,?,,...,,,...,..,,,..,..,,,;..,.,;.;;.,;,...,...,.,;,..,.,,,,!!!.
.,;,,?,.,,;,,;..,.,.;.,,..,;.,.,,.???,,.,,.,.,;,.!.,...,.!,...,..,,.,.
.,,...,,...;..,,..,...!..,,..,.,..,;..,,.,.,,;..;,.,;;,.,;...,.,;,.,,,
,,,,;,...,,.,.,.,;..;,.,,,.,,..,.......;.,:;,.,.!.,;,...,.,...,,.,,,,,
,,;.,,,,,.,;,,,.,,,,,,.,,,,,,.,,.,,.,.,.?.?,.,.,.,,.,.,...,,....,;.;..
,,.,!...,,..;;..;..;.,.;.,,,,.,..,,..,,,.;,,;,,.,..,,,,.!.?.,,.,,,..?.
;.;.,,,,.,.,,,..,,,,,,,,()...,,,;.,.;.,......,,,,..;;,.;,.;,,,,.,;,,.;
,..,;.;,,,,,,;,...,..;.;;,,.,,,.;,,,;,,,,.,,.,,,.,,;,,,.,,.;.,,;,,.,..
.,,,,.,,.;,,..,...,,,.,.,,,,.;;,,.,.,,,,.,.,,.,.,;,...,;,,.,.,.,;,,,,,
;;,,,,.,,;,,.,,,..,,.,;,,,.,;,,..,;.,,,,,,...,;,,.,,...;,.,,,,.,..,,.,
,.,.....,,..,,;.,.,.,.;..!,,,..;..;,.,;..,,.,,,,...,.,,.!...,,!??.,,,.
,,,.,.,!.,,.,?,.,,....,,,,,,.,.,,!,,,,,;,.,....,,,,.!.,.,;..?.,..,,.,,
.?..,,.,.,.,,.,,?.,.;..,.,.,...;,,,.,,.,..,.,.,;.,..,.,.,..;,,.,,,.;,,
.,,...;..,.,;.,,..;..,,,.,,.,,?.,..,.,?..;....;.,.,,;,,,.;,.,..,..,;..
,,,,.,..,..,;,,,,,,,;,,.....,..,,.,;,.,..,,,...,.,.,..,..;,,,,,,.,,,,.
,,..;,;,,,.,,..,,,,.,.;:.!!.,,,.,.,;,;,,:,,.,...,.;,.,?,.,,.,,..,,.,,.
,,,,.,,.,.,;.,..,,,..,;,,,,...,?!.;..;.?,,,,,.,,?.,?,..?..,;,.,.,.;,,.
,:,!;,,,;,,.,,,,.,,,.,.,,.!...,,.,,.,,;,.,.,..,.,.;..,...;.;,.,.,...,.
,.,!,,......,.,;;..,:,;,.,.,,..,.,,,.,,,.,,.,...,,.;,.;,.,,,;(,.,.,,,.
,;,.,;.,.,;.....,.!,...;,..,,,.;,,.,;,,;,,.;.;,,.,,,.,,..,,;,.,...,,.,
...;,,,.,,;,..,,,..,,,.,.,,..;,.,,,,.,..,.,.,,..,,,,.,,..,,..,;,...,,,
,.,,,,?,..,,..,,,.,,.,.,,.;,.;.,.,,,.,,,(;;,.(;,,,,,.,.,.;,.;,.(,,,,,,
..,,;,,,..,..,.,,,;,,.,.(.,.,.,.,,.,,.,.,,..,,;,,.,.,.,.:,.,;,..,,.,..
,.?,.!;,.,,,,..;,,.,,,.,,,,.,.,,,.,,.,...,,,,.,...,..,.?......,...?,..
,,...,,.,.,.;.,.;;,,....;,;.,.,,?.,,,,,.,,..,,,,..,....!.,.,,,,.,,;,,.
..,.,.;;.,,....,,,..,.,,.,,....,,.,,.,,,.,.,.,,,,.;.,.,,,.,;;,.,;..,,,
,,,.;,.,.,.,?..,;,.;.,.,..?...,,;,.;,;;;,.,,?,.;;,?,?..,,..,....;,,;,,
,,,.,..;...,.,?,,,?,;.,..,,.,.,,..,;,.,,,,..,.,.;..,.,,.,,,;,,..,...;;
,.;,,.;,.,,;.,.,;..,.;..;,,.,,,.;.,,.,;,,.,;,,.,,.;,,?.,,..;,,.,;,.,,,
;.,.;,,,....;,,.,;,,.,?,,,.,,.,,;,.;,,....,,.!,.,,,,,,,,;:!.;;,.,,,;,,
..;.;.;.:;;...,,..;,,!;;....;,.;.,,,.,..,.,,,,;,....;.,....;...,.,,.,,
,,,,,....;.,..,.,.;.,,.,,,!,...,.,?..,.,.?,,,.,,,.,,...,,,..;,,,,.,,,.
,;;,;,,;,,,.,,.,.,,..,,,!;..,.,,,....;,.;!,..,;;,.,;,.,;,..,,.,;..,,..
..,..,,,,?;..,,.;..;;,,;.;,.?,.,.,.,.;..,,.,,,...,...?..,,.,,....,,;..
,;,.,.,;,.;,.,,.,.,,..,,........,,..,,,,...,.,,.,,,,.,!,,.,..,,,.;,,,;
.?,!.,?.,.,.,,,;,!?,,;.?..,,,.,.;,,.;,.,.,..,,;,...,.,,....,,.,.,.;:,;
...;;...,,,,,.,,.,.,..;,,,?,.,..,,...;,,,..;,.,,.;,,.,,..,.,,.,..;,,;;
.,,,;,,;.,,,.;.;...,.,,.,.,..,..,....,;.,,;..,,.,,,;.;.;,,.;.,.;,;,.,,
;,.,.,,..,..,.;,..;,.,..,.,,.,,.;,.;,,..,,,,;.,.;,..,.,,,.;,.,,,.;,,..
,.,,,..;,;,,,,;,..,,.,;.,..;,.,,,.,.;,,..,,...,?,,,,,.,.,..?,,?..,..,,
,,.!;.!,..,.,.,,,.,!.?,..,;,.;,.,,....,,,,.,..;,.,,,.;,,.,,.,.;,,,,.;,
,,.,.,,.,,;,,,.;.,,...,,.,...,.,,,,.,;,,,,,,,.,,;,.,,,.;,,.?,.!.;.?.,.
,...;,,.;.,...,,,,.,.,?(,!,,,,..,,.,,....,,.,,,.,.;.,,.,,.,.,,,,.;,,..
,,;,..,.,.;,.,.,.,..;;,,,.,,,.,.;,.,,,.,,..,,.,..,,,,.,;,.,.,,,,,,,,..
,..,.!,..?,.,,...,.?.!!..,.,.,,,,.,....,.?..,!.?,.,,..!.,.,,;.,..,..,.
.,,..,.,...,..;.,,,.,.,,.,,,,,,.;;,,;,.,,,,,..,;,.,.,;;;..,,,.,,,;,..;
,.,,,,.,.,..,,,,,,,.;,,..,,,.,,,,.,.,,,.,.,;...,.?;,..,.,,;,,..,.,.,;,
,.;;.,,,;,.;,:,?.,.!..,...,..,;.,..,..,;,,,..,;.,,.,,,?...,;.,,,,.,,.,
,...,?,...;,.,;.?.,?,.,,,,,.,...,...,..,,.,..;;,.,.,,.,.,.,,,,.,,,,,,!
;.?,,:.?;.,.,,.,,.,..;.,.....,,..,..,?.,..,.;,..,.,.....;,?,,.,,?..,,,
,..,,,.,,.,;,,;,...;,..,,;,.,.,,,.,;,;,.,.;;,.,.,,.,.,,.,;,,;,..?.,.,,
,..,.,,.,,.?..,..,.,..,.?,?.,.,.,.,;,,.,,.,,,,..??,,;,.:..,...!.!.,...
?,...,,,...?,.,..,.??.,,.,.,.;.,.,....;.,,,.,;,.,;,.,,.;.,,;,.,;.,.;.,
..,.,,,,.,.,,,,;,,,,,,.,,,..,.,....,;,;.,,,,,;,.,,,..,.,,,.,...,,,..,.
.,..,!,.,,,??.,,?,,:..,,,.,..?:,.,.,...???,,,?!.,...!.,,!,,,.,,,...??;
:,,,.,:.;.,,,,;.,,..,.,,.,.!,!.,,.,.,.;;,.,,,,.,,.,.,;;.,.,.,,.?,,,,,.
,,,.,;,,,;.,,,.,,.,,,,,,,,.,,,,,...,,.,;..,,,.,.,.,,..;,,.;,,.,,,,.,,,
,,.,,.,..;,,...,,,.,,.,,,.;.;.;.,.,,,.,..;,..,;,,,,.,,,,.,,,...;.,,..,
,,,,,.;.,,.,.,,;,.,,,,,,.,....,..,,,;,;.;,,,.;.,,.;..,;..,;,.;.,,;.,,,
,.,;,.,,.,..;,,,.,,.;,.;..,,.,,!,,,,,,,,.;.,;.,;.,,,..;.,..,,,,..,..,,
;..,,.,,;,.,,.,.,..,.,..;.,;;..!;,.;,.;,,,,;,;.;,.,,!!!,!,,,,,.,.,.,?;
..,.,.,,,..,;,,.,,,,,,.;,,.;.;,,,,,.;,.,,;.?..,.,!.;,...,,,:,.,,,.,...
.!.,,,,,,,......,.,.,.....!.?,,,,;,,....,,;.,;.,;.,;,.;,?,;..;.;,,,,.,
,,,,..;,,,,.,,;..;.,;...,;,..;,.:.,,...,,.;,.,,.;.,...,.,.!;,,,,,,.,,.
,,.,,.;,!!!,,!,!,;..,,.,.,,.,,;,.,,;,,.,,.,,?,,,..,,,;,,,!.;!;.!,,,,!,
.!,.,,.!.;.:!.,,..?,,!,;,,,,!..?.,!!,..;!.;,,;,.;!,...,,.,..;.,,;:,,,,
,.!!;,,,,!.!!,,...,.,.....,.,.;,.;,,.;.;.,;!,,.!?.,.,.!,,.,.,..;.;.,.,
!,!!.!..;,!!....,,;.,.,.!....,.,.?..;,..;........,.,.,.;.,.!,..,,;,,,.
,?....;,.!;,,.,,,.,,,,,..,...;.,...,..,.,,.!.,;,.,..,!,..,....;.,,.,.,
,,,,;..,,.,.,;,.,.,.,,.,,,.??....,.,..,,.,;;;,..,,?.:,;,..,....,.;,..,
,,...,.,,,.,,..;,..,;.,.,,,;,,,.,,,,,.,,;,.:?.?,.,.!,,?,.,.,,,,,,.;,:,
.,.,,.;,.,.,.,;,.,,..,;,.,.,,.;.,.;.,.;,.,.;,,,,.,;,,..,;,,,.,,,,,.;;,
,..,.;.;,,;,,;,,.,,.,.;;,,.,..,,,,,,.;.,,,.;,.;..,...,.,,,,,,.;,.,;,.,
,,;.,,.,,?.,.,.,..,;....,.,.,???,;,,.,;,,,.,.,,,,,,,..,.;!,;..;,.;,.,,
,,;,,.;.;,;,,!,,.;..,;,,!..,.,,,...,,.,,,...,,,;,,.....?.!!;.;..?,;.,,
,..,.,,;,,,..,..,.,;...,,.,.,,,;.,;..;.!.,..;,;,.,....,.;,,,,....,..,.
.?,!!!,,,;,,,.,;,,.,,,.;,,;.,.,.,,.,;,.,,,;,,,;,.!!!!?,;..,!,,.,!.,,;;
,,,,,.;.,.,,.,,,,,.,.;,,,;;,.;,,.,,,,,.,,,,.,,,.;.;,,,.,..;.,?,,,.;,,.
..,,,;,,,.,,.,?...,,,.,.,.,,,;,.,.,...;,,,,?;.,,.,;..,.,,,....;.;.;.,,
,.,.;..,;.?;,.,.,,,,....!..;,,;,.,,.,;.,.;,,..;.,,,,.,.,,,,.,.;,;,.,,.
,..,;..,,.;....;,,.;.,...,.;.;.,;,,,.,,,.,,.,...;,,,,,;..;,,,..;,,,,,,
,.,,,,,.;,.,,,,,.,,,.,.,,,,,,,,...;...,;,,.;,,..;,.,.,;,,,.,;,;.;,.,;,
,,,.,,.,,,,,.,;,.,,,.,,,,;.,,.,.,,.,,,,.,..,,.,.;,.;..;.,,,;...;,,.,,;
.,,,,.,,,.,.;,,,.,;.,,.;,,?;;;,.,,.,;,,..,;,,.,.,;,.,,.;,.;.,.,;...,.,
.;.,,.,,,;;,,:,;,,..,,.,..,.,.,...;;,,..;,..,;,.,;..,;,,.,,(,..;,.....
..,,,,.,;,.,.,.,.,.,,,,.,.,,,.....;,?.,....;.;,,.;.,.,;,.,;,!,;,.,,,..
!;;.,.,,.,,,,??,..,.,.,.;....,.,,.,?,,.,?,;..?!.!,..,,.,.,,;,,,;,,,,,,
,!,,.,.,.;,,,,;,,.,.,,,,,,.;,..,..,;.;,.,;.,..!,,,,,.,;,,.,.;.,,...;;.
;.?,.,;,,,,;,,.,;,.,,.?,!?.,.,.,,..?,.!!.,,.;,.??,..,,?,.,;,,,?,,.,.;.
,.,,;..,.?,,,;;.?.,,,.;.,..??,.,,.,;,?...,.,,.;.;;;,,,.,,,,.,.,,.,;,,,
.;,,,,.,.?,?.,,.?,..,?!,,,.,.,,.;,,,.,;,;.,,.?,.;.,?,,;,..,,.;,.,;.!.,
,,,,,,,.,.!.,,,,.,,,,.,..;,,.,,,..,,:;;.,..,;,.,,,,.??.,..,:.???;,.,.,
,?,.;,,.,?,??.,;,,,,.?.,:,,,.,,,,,..,;,;..,.!.!.,!..!!?..,!....,,..,..
;,.,,.;,,.,,...,,.;,..,.;.;..,,,,,..,.,.,,,.,,,,.;.,;,,,..;,;,;,,.,,..
:,,.,.,.,.;.,.;,.;..,,..,,,,.,,,,.,,.,..,,;,.,.;,.;,,,,.,,.,.;.,.;..,,
.......,,,..,.,.,.,.,...;,,.;,,,.,...;,.,;,,,,.!..?;,,.:,,.,.,!,;.,,.!
,,...,.,,..,,,,,,.,,.,,;;,,,.,,.,,,,.,?..,.,,,,,.;,!:.;,,;,,,,,...;,.,
.;,,.,...??,.?;.!..,.,,.;.!!,;;,!,,.,.!..,.,!?..,.!..,.,.,,.,,,,.,,.!!
!,:,.;,.,,..,.,.?,,.,,.,,,..,,!!!!.,,.!,.,..,?,,...;.;,,,.,.,,,,..!;..
,,.,,,,,..,,,,..,,..,,,.;,,.....,,.,,,.,,.;,,.,,.,.,,,..;,;,..,..,,,,,
,.,,!;..,..;.,...,,.,,;,..;,,,.,,..,,.,,..,.,,!,,,,,.;,,..,.,,..,;...,
.,.;.,..,,,.,.,?..;,......,,,;,.!,.,,.,,,,,,.;,.,,.;.,.,,...;;;,,,....
,,;,,,,,,,,.;...;,,..;.,;.,!.;,!;,,,,.;.,,,...,.,,,,?...;.,.,,.!,;.,..
,..;,;,;,,,,,;,..;;,.,,,,?,.!,..;,,.,.,.,;.,..,.,,,,.,..,!.!,.!.,,,,;.
.,.,,,;,,.,,(.,;.,;,.;;,.,,;.,,,,.;,...,,....;,.....,.;;.,,,,.,..,.,,.
.,,,,,.;.,,,,,,.,....,.,.,.,;.,,.,,.,...,.,:.,..;,.,.,,,,,,.,.,,..,,.;
,,,.,;,..;..,,,,.,,,.,....,(,.;,;.,..,..,.,..,,,!;,,,...,,...,.;,.,.,,
.;,..,.,;.,,,.,;...,.,,,..,?,..,;..,....;?.,...;?.,..?.,;!!,,,..,,;,.!
,.,;,,..;,.,,.,,,.!,,....,,,....,.,,..,..,,.,,..,..,,.,.,;;..,..;:,;.,
....,;,,,,!,,.,,..,,,.,.,,.,.,..,;..,.,.,!,.,.,.;,,..;,,,?,.!.!...,,..
;..,..,,,,.,,.,,,..,.,,..;.,,.,,..,,..,.,,.,,.;,;,,.,,!?;.,,...;,,.;,.
.,,.,.,,,,,,;,!.,,,;..,,.,,!,..,.!!,,.;.;.,..,,.,,,;.,...;,,.,;..,,.,;
?,,,.,....,,,?.;,,,;,,,,,,.,.,.,..,,,,,.;..,.,,.;,.;.,..,.;;,,.,,,;.,;
!!?,?!,;?,?.,;,,,,,,,..,,..;,,?,..;,;,,?.,..,;,,,...,.,.,,,,,!!?.,..,,
..;.,,,.?,.,.,,.,.,,.!!,..,,,.;,?,;,,,.:,.;,.,,..,.;,.;,..,;,.,.;,.,,.
..,;.,,.,,,,..,,,,;,.!.,,.,.;;..!!,,,,.,!,,.?..,..;,,,,,.;,,.,;,.,;,,,
.;...;,..!?.,..,,.!,..;.,;;,.;;.,;.,!.,?.,.,;.,..,,!;.,.;,.!.!!,..,..,
.,,.,,,,.,.,,,,.,..;;..,,,.,,,,...,.,,.,.,.,;.:.,,..;,,,.,,.,.,,,,.;.?
.,:,...,.,,,,,.,,,,,,,,.?.,,,!??.,?.....;.,.,,.,;,.,.;.,.,,,,,????,,..
.,,,,,.,;,.,,,??,;..;..,,.;,.,.,.;.?.,,,,,:..,?........??,.,.,.,,,.,.,
??,....,!?,.?.,,..,,.,,..,,.!..;.,,,..;,..,.,!!.,.?;.,,,,.!,,,,..,,),.
,.,;,,,;,,.,,.,,,..;.,,..,.,,,;.,,,.;.;.,.....,;,;:.;....,,,,.;.,,.,,,
,,,.,:.,...,?,!,..?!,,,,.,,..,.,.,.,.!,.,.,!!.;,,.,,.?;,..,,,,,,...,,.
;,..;;.,;,.,.,..,..,,,..;,,,,.,.,...,...,,,,,.,.,,;,,,,.,,,;,;.,.,.,,.
,.,.,,..,,,.,,.:.,,...,,.!...??,.,.,..,;,,,,.,.,,....,,,,..,,(,,,;;.;,
,,..?.,,..?!.,.;.,.,,;,.,,;,,.,,,,,..;.?.,..,,..,,,..,,?.;.,..,.,.,.,.
.;;,.,.,,.,;.,,.;;,.;;..,.,,!;,,....,...!.??..,,..!?,.?,.,..,..,;..,.,
,..!..;...!,!?,.,;.,,;?...,..,.,,.:,.,..;.,;,.,..;,,,.,;,,,,,,;,,,.,?.
;,...,,...,;.,.,;,,,,,,,.,,..,;,.,.;.,.,,.;,.,,.,,;,,,.,!!!,.!..!.:,,,
,..,;,,..,,.;.,,.,.?,?,,.,,.,...,..;,,.;..?!.,,;.??,....,,!,.!.,?.....
..,,???,.,,.?,,.,,...,;,,,,;.;,..,!.,......,,....,,,,.;.,,..,..,.,,,.,
,....;,,,,.,,;,,.....,,;,,...,..,;,,.,.,;,,,,.;..,;,.,.;.,,:,.,,.,.;.,
,,.,,,,,;.,.,.;,.,,,;,,.;,,.;..;,,.,.;,,,,,,;,,.,,,.
The Metamorphosis by Franz Kafka (1915)
extract_punct(
  gutenberg_download(5200, verbose = FALSE)$text,
  width = 70
)
,.,,.,?,.,,..,,,.,,,.,.,,,.!;;..,.,.;,,,!,....,!,.;.?,?,.,.,?.,.?,.,,.
.?,.,,.,:,,.,,,,::?,.:,,.,,.,.,.;.,;,,;,.,,;;,,,,.,.,..,,,,..,.,.,,.:.
,...,.,.,.;,,,?...,..,,.?,?,,?,,,,.;.,.;.,.:..,...,,.!;...,;.;;,,.,,,.
?,;.?.?,?..,.,,.,.,?,.,,,.,...,.;,,,,,,...!,.!.;..,,!,,,.,;..,,.,;...?
,,....?.,,,.?;.,,,,.,,.,,..,..,..,;,,.,;:!,.,,.,:..,.,.,,..,,..,.,.,.;
;.;,.,..,,.,.,,,,.,.,...,,.,,,,,.!,.,..,,,..;,.,!!.;.,,,;,,,,;,;..,:,,
;;;.,,..;;.;;.,,,,(),.,.,,,,.,.,,.,;,.,.!,.,,....,;;,.,,,.,...,..,,,.,
.;..,,.;.,,.,.,,.,,.,.?,.,;;.,;.,,,.,,.;.,,.,,,..,,,,,,,,,.,.,.,,?,,..
.,,.,;;;.,,,..,.,,.,;,.,.,.,.,.,.,,,.,,..,,.,,,.,,,.,.,,;..,.,;.,,.,.,
,,,....,,.,.,..,,,,,..,.,.,.,,,.,,.,.,..,,,.,,.,;,;...?,.,,,.,,.,.,,,,
,;,,,.,.;,,..,.,.;,.,,,.,,..,.,.,...,.,.,,,,...:?,,,,..,,,,,.;;,.,,,,,
.;,;.,,;..,.,.,,.,,.;,.(,,?.,,.,?,.,,;;.,,.,,,,,,,....,.,,.,,,,.,.,.,,
,.,.;;,,.,.,,.,.,..;.,.,,,,.!.,,,:.,.;,;;;;;;;.,,;,,.,,,.?.:.,,.,.,,,.
,!..;.,,;,,,,;,.,;;,.,,,,,.,,.,.,.,.,,..;;,,,.;.,.,.,,;,,(),,.,.,,,.,,
.,(.,,,.,,..;;;,.!.,;,..,,.,,.,..,,..,!,.,?;;.,,.,,.,;,.,,,..,;,,.,,;,
,,,,,,,,,,,,,.,..,;..,,,,,.;,,;;,,.,,.,.,.,...,,,.!,.,.,.,..,,,.,.,.,.
,.,,...,.,,.,,,.,.,,,,.,..,,,,.,..,.,,,.,.,,.,,..,?,,?..,.;,;;.;,..;,.
,.,;,,,.,...,..?.,,,;;,?.,,,.,.,.,...,..,,,,..,.,,.,,..:..,,.,.,...,,.
.,.,,...,,.,,,,,,?,,.,,.,....,.!,.,.,.,,...,.,....,.,.,,..,...,!,...,.
,....,.,.,.,.,.,:,.....;,.,.,,......,,.,,...,;?....;...,.,....,;...,.;
;.;;,,,;.,.,.,..,.,,..,,.;,.,,,,...,..,,.,.,;,,.,,...,.
Moby Dick; Or, The Whale by Herman Melville (1851)
extract_punct(
  gutenberg_download(2489, verbose = FALSE)$text,
  width = 70
)
;.,,..;,,;,,'.;.,,.,.,,,..,?.;!,;,?!.;...,,,?.,,.,,.,.,.,.,;;,.,'',?!,
,,?,?,??,.,,,;.,,.,.';,..,,,,,;,,,.,,.,,',,,,.,..,?,,?',,,',,.,..?,,.!
,.,(.;,.,;,,.,..:""",,,,;,,,...;;,,,,,.,,,,,,.,.,,,,,,,,,;.,?,,?,,.,.,
,,,',",,,,,,.,.,;.,.!,,.,.;.!,"",.;.;,.',,,,"?..,,,.,,,',,,",,,.,,'..,
.,,,.(,!;.???;?,,.,,.,.",,.,,,,.,,,.,,,.,,,.,,.,'.'.',??,.;;,..;,.,,..
,.,,.,.,.,,',.,'',',,()..,.,';,,,,."'.;,(,,'"',.,.,,.',,.,,."."".,"?",
",.,,..,;,;.,,.,,,.,,,,.,,.,,.(),.,;.,,.,.,,".',...,,,,,,,,.,.,,..,?"'
",.,;,..,,.,,.,;,.,,,,,.,',.,,!,'.,'',,"?,.",,,."?",?",""""""'"'""""",
;.,,.,.,,,.".,,'',',,.,,,?"",.''.,,,',;"'',,,.";",,,.,,.,,'.,.?,.,.,.,
?,,.,.,,,,,,',,,.,,.,,.,..,,,,.,',!.,'.,,.;,,,,.,.,'..,.,,,....,.,,.,.
,,.,.,,'.,.,..!,,.,,,,.,,,,,,,.,.,;,.,(;,;.,,.,.,,,.,,,,,,;.,,,.".".",
.,,"."?"?,?"."...,'',.";.','",,..,,,,.,;..,,.,;,,.,,,.!;,.,,,:.,.,,;,.
;,.,,.,;,;,.,,,,'',.,,".;,',,",,,,,,.,.,,,,,,;,.,,,.,.,,.,,,;.,...,;,.
,,,.,,,,,.,;,,,.,,,,,,,.,,',.,.,;,,.,.,;,,,,.',.;.,.?',".,,,,.,,,,..,;
.,,;,.!,,.,,,,'.',,,,,.,.,.,.;..,;.,,,,,.,..!,',.,.,.,,,,..,,.;;.;,?,,
,.,,;,.,.,.;',;.,,,.',,.,.,,.,,,.;,,,:,,,,.,,,',,,.,,,.,,..;,,,,,.!,.!
,..,,!,,;;,;;;..,.,,,..,,,...,.,;,.;,,.,,.,;,',,,.,,,.,;.,,,,,,,,,.,,,
.,,,,,,,,..,.;,,?,,.,',.,,',',!..','?'.,.;,.!!,'.;,.,;,,,'.,;,,,.,;,.,
,.,.,,"'".!'!,!?;.,,,.,.,,,",,.,...,,,,,,.?!,.,,,',.;,,';..",',',,.,.,
..,,"'!.,,,'...'','.",,;.';;.,.,'.'.,',.,,,'"',,;,;,..,';",;,,,''",,!.
,;,,',,,.,,,',,.,.,,,.",;,,.'.?,,,,."!,,,.,,;.;,.",,.;,',.,.,,,,,.,.;,
,';;,.,;,,,:".;,,,,,,.,,',,'',;,,';,'!".!!!!,,!,;,,,,.,,.,.,.,,.,,,:?,
,.,;,,;,.,,;,.;,,...,;.,,.,,,.,.,,.,,;.,,...,,.;.,;;;;..,";,;,;..,.;.,
..,,;'.;.,,..;,,.',;,,;;,,.,.,;,,;',.;,,;.?.??.?.;;;;,.;.;.,,,,;,,.,,;
,.;,,,..,.,,.,..,;,,.;,,'.,;.,.,.'.,,,.,;.,,,.,.,;.;.;,.'.,',.;.,,,;;,
,;;.,.,,,,.,;.;;;,,,,,,;,,,.,.,,.,.,,.,,,,;,,,,',,,,,,,'.,,";,.,.,.,,,
.,,,..,,;.".,,;.,,'.',,,,,,,,;.,,;.",,,,,;,,,,,,,!;.,;,.;.,,,;.,,.,,;,
,.""",'"".",;";,.,,.;,,.,,.,,,,,,,.,,.,.,,,,.;;.?.;,,".;,!;.,.,;;;,;';
,,.....,,',!;,,;';,,!,,;,.;;',.;.,.,,.;,.,.,.,;,.,,,,,,.,,,,,,.,,.,,.,
,.;';!?,,,."";.,.,,"""",',","?,.,!,!,,,,.,,,,.;,'"',;,..;.,'',,;,;"?",
,;.(.,"..,,,,,,;,,,.,';,,,;'.,;,.,,;,,,.,'.;;.;,.,;;.;.,'..,.,.,,,,,',
.,.,,,.,.,,,.,,;,.;.,,',.,;,.,.,;,,,.."."?""?"""'"?.!.,,,?.,,,."."""""
".,.,,,."",!,,,,.".?"""'!?""'",",?.,.,,'.,,.,."""'",',..""..;,;;,,.,,,
...,;,,,.,;,,;',,',,,..,.;,.,,,,,,..,;,,,,,',.,;,,.,,.,,,,,,,,,,,..,,.
,.;,.;;.",.,,,""""".,,,,,.;,',;,,,,;,'.,,,.,,.,:;,,',,.,;,""?"',,!,,,,
,;"!";."",,,,.,"".",,;,".',.!,,,,,.,..,,.".,'',"?""."?"",'.,;,;,,,,.,.
,.".""',,'.,',';!!'"?".".,.,,.','.;,,,,,'..,;,;,,.,';,.;,,.',',;,,.,,,
.;?;;,.,,."".;;,,.',',,"...",;,..,.,,."!!,,""!",?.',.,",,"!.',;.',.",,
''",;,.,,,;,."?",,,;,.",,;,,,.;,';.,(,',.;;,"..,,,,.,;,;;,,;,,,;;,,,';
;..",,,;;.,,.;..,;.;,;'.".,,;,,,'.,.,;,;.,.;,,,,,,,,.",""',?",."',,,."
""'"''";.",?,,,;;;."";''.',;,?,,;:",''";",",,.,',,?,,,;,..,,",,",,,,;!
'.".'.;,,."",,,,,'",!?;,!;;,..,,",,,.;.,,."".",."""""''"",.";'","."""'
".".;""",".',;?,?.,?';,;",.,,."",,,?;',,'";;";,'".""."!',,,,,,.;.,,,;;
,;;.,,,;,,.,,.:;.'',.,.,;,.,,.',,.,,,,.,,,;,,',,,'''.,,,,.,,.,,.,,,.,,
.,;.,,,.,.....'.",;",,,.""""",",",.""".",,?,;";,'"""''',.,,,,,.,.",,,;
;';""'",,,',.,,,,;,,.;,.,,"",,,.;."""."",.";,.;..,,,,,,",'""!,.;,,,,.,
,,,..".";,.".,.,,,,,,,,,;',.;,.,,;,.."",;,,.,,,,,;,.,,,,".,...,,,,,..,
,,;;,;,;;,,;;,,,,,,,.,,,,!,.,'.".,',.'.',,,,.,",;;,.,,',!,,.;;.,;,,,;,
;'';,;;,,,,,!,,!;;,.,,.,,,.,.,;,,.,,,.;'','!,;!,!;,'?,?,,;;,,,,;,,,.,,
,.,..,,,,,,,,,,.,.,',,,.,,.,.,;..,.,,,.,;.,,,.,.,??,,!?,.?.;,.;?,,.?',
..,.?.,!..,;;,;,;.,.,,?,,.,,,.,?,,,.,?,,,,!,.,,,.,..,,.;;,,,,.,.,.,.,,
;,,.,,,,,.,,,."'",;,.,,;.,.'?,,,,;,,,,,,,.,';,;,;,.,;..,,;;!!,,;,;;;,!
,,,;;;,;,.,.;,.,,.,.,,..,..;,,,,,,,;...,,;.,.,;,;,;,.,,;,;;,,.;;.'.;;,
;,.,'.,.,.,,,,;,,'.,.,',.,.,,,,;..,,,,.,,;;,.;.,,',,,.,.,.,,,,,,.,,,'.
,';,;!,.,;,.,.,;,.',.,.,.,,,.,,.,,;.,;,,.,,,,..,.,,.,',,,,,,,,,,,',,.,
,.,.,,.,,.'""..',,,',,.;,,.;.,,,.,,.,,,;,,,.,,,,,;.,,;,,.,,,,,..,;.';.
,.;,,"",,,,,;,;,;;,,.,,,,,;,,"?;.,",".",",,,",",?;',!'.,'',,,!;..,;?'.
,,,,.,',,,,'.,',.,,,,,,,?,.,,.,,,,,.?,,'.;...",,,.,,,'''.,,,,.,.;,.,,,
'!',,,,,,',',,'?,.'?,,.,;,;',.!"",,.",",,,,;.;;.,.,..",".(""".,.,,,,;;
;;;,.;.,,.,..,,;,,.!!,.,.;,.,,,,.,;.,..,;.';!.?;;.:,.,,,,.,,,,,,..,,,.
.,:.,..,,.,,,.,;.,..,(),,,;.:(..;;..;..,,.;;;,,.,,;,..,,.,;...,.;.:;;.
,?;;;,,,.;.,.,..,,,,,,,.,,,.,,,,,,..,;;;,,,,,,,;;'",,,,,,,,.,,;.,,..,,
.,?.,.?,;,.....,..,.....,..,.,.;.,..:;.,,,,..,,,,,,;,..',..,...,.,,,,.
.,.,,,.,..;.,,.,.,..',..,,"",.,.,,,..,.,.,,.,.;..'......,,,,,....;.,..
,..,.....,,...,,,.;.,.;.(.,,",,..,.,,,;,.,,,;;;;,,;,.:,.,.;,.,,,,,.',,
,.;.;,.,,.;.,,),,;,,,,;.,.(,,,,;,,,,,;,.;,;;,,,;.,,.,;.',,,,',,.,.,;.,
,,,;,;.,!;,,;,..,,.',,,,,,,",;,,',,,,,'.,,;',;..,.,;'...,,.,,..,,.,.,'
;,;,,,;,.,;..,;,,,,,,,,...;.,,;.,,,,,;,''',,.,',.,..',.,,.;.,,,,,,.',,
.,.,,',,,.,',;,.,.,,;.,,,.,,,;,.,...;,,,;,,.,,',,.,;;;,,,.,,,!,.',.,,,
,.,,,;,,,,.,,:;,,,,,;;,,;,,.,;,.,.,;,,,;,.;,,,,,.,,;,;(:,,,..;,;;;,.,,
.,,,,.',(,',;;,,(),,.,,.";''',,().',.,.,,,,'(,;,.,,,'"';,,",,,.,,,'.;.
,,;,,.,.,'",!;.,;,.,,.,:".,",.;;.""..;,,,,,.,;,.,;,,;.,,,(,,.,.,,,,,,,
.,,,;.".;,..,,."."',,,,.,;,..""."."""",;,.,,,"."',,,,.,,:;,,,"."",,,."
."".",",""";,;,!!",."?",.,;;,",.!,,.":!""'!",,,?".,,;!","!,".,.?,';.;,
,,,,.';,..,,,,?.,..,,!,(.,",;;;,';;,,,.,.",.,,'.,,;.".,';;'.",;.!..".,
,;..,;.",..,??.,,,,"!,!,.",..,!!,.,;,.;;';,.;.?;,',;!?,;';!(',.;,';';.
,,,;'...!,.,';;,,;,.;!,,.,.,,.,!.!.,,,.!,,!',,(!,?',;.,,.','!','',,.?(
,,(,,,',,,,.,,',,!',!,'(!,';'';'.,.!(',',!''.;,!;,,!(,!(.(,!,,!!'.,!,;
,!,(.!!('',',,(!!!,(,,!;!?'?('!.,!,,,,!!!!!,',.,.?'((.(..''';(,(!!('!!
!..''!!(?!!!,',,!!'!;!,;,,..,.;;,,,,,;;,.,,,,;,.,,;,,,,.,;,,,,;,;,.,.,
;,.,.;,;,.,,;,.,,,,.,,..,,,,,,,,,;,,,.;,.'.,(".;,,.,,,;,.,,,;,,.,,;.,.
,,;,,,.,,,.,.,,,()().,,;;,(,;,,.,.,,;,,,,;,,,.,,,,,.,,,.,;',.,,,',,;,.
,',.,,,,,.;;;;,,;;;.;'.,,,,,,,;;,,,;,,,,,',,;,;;.,.;,,;.,,,;,.;,,,;,,,
,.!,.,,,;,,,,,,.,,,,,,.,;,.,,.,,.,!,.,,',,,,,.';;,,,,,,??;,.,,,',,;..;
,.,,,;,";;;,;,;,,;,,;,;;,;;,,,;,,;.,;,,.,,,.;?,,.,,,;,;,;.,,.."(.,,,,?
'.,,,,,.,..,,..,;,!'',,..,;;,.?;.,;,,!;,,,..,.,,,,;,;,.,;,..,,..?,,.,.
.,,!,.,,;,,.;,,,,,.,?,,,?..,,,.,,,?,,?(,,,,,,,,,,"?,;;,(,,'.,;.,;,..:,
;,,;;;,,?:,,.,,.,,,,.,;,,,,,,?,;?;.,,,.,;;,!;,,,;,,'.,,?;;,,,;,,,,;,,,
,;,..?!":,,,,,,,.,,,"""."",".!""''";.,.",,,,;.,,.,,,,.,,;,,,.,.,;';,,.
,';,.,.,,,,;";;;,,,,,;,,,',,,(',,,.,,,..,,,;.,,.,,,.,,',,,,,.,,,.;;.,,
.,.,,.,',.;,,,,,,,';,,,?,,,,,!..;.,,,,;,,,;,,.,,,;.,,,,,,;,,,.,,,,,;;.
;,,,,.;,;.:,,,,;;,,,,.,,;,,;,.,',,.:,.;,,.,,.,,.,,,.!'?,?!?,!,..,,,,,,
.,,,.,,,,:,,,,,,,'?.?,,,',:;,;,..,,,.:,,.,,,".,.,;,,.,;;.'";,,.:,,,.,.
,.''.'?,',,.:",..;.,,,.,,.,;.',.,,,...,,.,,',,.,.,,,;.,;,,.,!,,.,,.,,,
,.;,,,,,,,,,.;,,,(.,,.,,,,.,,,...,,..,,..,.,.,,,,.,,',,;;'.,.,,.,,,.;,
,,;.'',,.',.,;(),.;,,,..;,,,,,,,,.,,,..',;,,,,.,.,,,;.,,.,,,.,,.,,,,,,
,,.,,.;.,,;';,.,,;,,,.,,.,,,,;',,,.""".,..".",.,.,.,,,;,.,.;;,.,''..,,
.,',.,.,.,;,.',"""",;;;,'',,,,,"",".!""',",,"?.,.;,,',',,''!;.;,',..;,
,,,,,,,,,.,',"!";'""(:(.(.,.",,.''!,',.;';',,.,,.;,.,,,;,,;.,..,,."!,,
.,,.',,..'.,,.".,,."".,',.,.,.,;,,..,;',.,,;,.,,,,,,,;,,.,,,,..,.";,.,
.,..,,',,!;;'",,?,'?,,'!;.,,,"',.;,;,!;,;,;;,,,,;,;;,,,.;..,,.;.";',;:
",,;.,.";.,;;.,,,,,,,.;,,;;.,;.,.,;.,.,.,.,,,.,,.,';.,.,.,,.,',,,.,,,.
,;,,,,";",.",,,,'".";,.'"'.,,.,;;',,'':.",,..,;,;.;,.,,.'"".!"..,",,.'
..;;,?.,,,.,.,,;,,:,,;,';,';.;.'.,;;,,;,.,,,.,';;.,,,,',,;,,.,;;(,.,;,
...,,,.,;,;,,";.,.,'.,,,;,'.,.,,..,,;.,,;,,.,,,;,,,,,,.,,,,,,.,,;,,,.,
;,,,,.,.,;,,,,,;.,,.,..,,,.,,;,,.,.;;.',;,...,.,,.!.,,(,,,.,...,;,;,,"
,,;..',,,,,!,,,,,',.",.,,,!;,,,,,.,;.:,,,.,,.,,.,;,,;,,,'',,,,;,.,;.,,
,'.,;.,,.;,.,.,.;,,,,,;.,.,,,;,,,,.,,,,",,',!?;,",';..,,.,.?,......;',
.;,,,',..,',,,.,.;,,;,.,,,;',,,'.'(,,.,..',.,,.,,,,.,,',.,.',.,;.",,..
.,;,,;;.,,",,,;,,,,,.",",,;,.,,,;.;,,;,;,;,;,;,;,;,.,;,,;,.;,,',,,",.,
,;,,.,!,,.",;,.,,,,.,,;,,.";,;',,',';,",.",,.,,;;,''.'"''';'",,.,;,,."
;.;.,,;;,..",.;.,';,,,",,,,,,;,'";,,,",.,;;,,:".,;;,,(,;;.".",?".",";.
";;,;;;,,.;,,,,",",",.!",",!",.,,.;.;.,;;,,,;,,,,,.".'..",,,,.;,,.,,;,
,.",'";,.,,."",!",..",';;;'?;;'""',;''"",,;'"'";,.",,.,,,",;,;,.";,;,;
,;,,,.,..."""",,;,;(),,.;,.,.;,,,",,,;.,,;;,.".,,.,;,''",,;,."',,,",,.
",,,".""";,,:,,,,.;,."",:',,.";,.'.,,,,,.,,,,.",(.',,,,.",,'.,,'.,."""
';,"""",,.;'.,',,"...",,,,"?"."",";",,.',;,,.,.,,,,,.,,,,;,.,,,,.;,",,
,;,,;.".;,".,,,.;;,,,.".;,.,;,"";"",,",,!",",,,.,.",,,",;."""??."'"".?
"";.".',".",;;.,..,.,,,',,.,',,,.,.,,.,,,','..?,",.,,.,.?,.'.,,.,,,".,
,.,.,,,,.,,,.",..,,.,!,.",,;,.,,.(),,..,.',),,.,',.;:..;,.,.,;,,.;',.,
.,.',,;',.,.,,,,.,",.,..,;.,.,,,.;.'',,,,..;.,.,,.,,,,..,,.,',,,.;;;.,
.,,.,.,,.,,.,,,,.,,..,,;,,,?,.',.,,,.,,,,,.().,,",;,,,,.,,(,.;;,,;,.;;
,(,;(.,,.,.;.,,,,,,,.;,,,.,.,,,,.';.,,',,,,,,...,.;".,,,.,;.,,,,;,.,,;
..,.',!,,..,,,,.,;,.",,,,..,.,,;.,,...;,,?.,;,;;,,,,;,.,.;..,?,;,.,;.,
,.,;,.,.;.;;?,,.!,;,,,.,,;,;.,,,,,?,,",,.,,.,;;,.;.,!,.,,,.;;,,,","".;
.,,.,;.,;,;.;,..,,.,,.,,.,,;,;;'.;,(,,..,;..,,",.,'.,,.;.;,;,;,,,.;,..
,.,,.',,,;.,,,';,,.,(,,;,.,.;,.,,,;.!,,,,,,,,,,;,,,.:,,,,,..,,,,,.,.",
,,.;,,,;,.;,,.,.,.,.;;;!,',,.';,,,.".;,,,,,;.,."'.,'.,.,,.,".',..,,,."
;,',,,'";..","'.,."...,,.;,','."),..,,;,,,,.;,.,;,,.",,,,,'...,,.,;,),
.".',,,..;",,.,;,,,,!"";..,,,,,,.,;,,'.,.,",,,,,;;;;,!,,,.,.,.;,,;,.,,
.,,.,,,,.,.,.,;,,.,,,,,,,.,(,.:,,,,.,,,,..,,.'';.,,,,.,,;,.;;.,,,.,,,,
;,,';,.,,',,,..,;(,,.,,,;,.,,.,,.,;."!,,();.;,,',,.,'(,..,,..,',;',;,,
;,,;,,,,,,.,,.",;,,,,,,;,,;,',,,",'',?,,,.",;,,,,".,!",',,"".",,'"'.",
.,.,'?;';,,.""'',','",,,"'",."."",""",,.""","";.".",,,,"?"",,,""'",."?
"."??"".',.',,'',",.";',.;,;,.,"?!"',.,.,,.,.,..,,;,,;,.,..",'.,..'),,
,.,....,(,';,,;',,!,;:,.;,;.'?;,,.,,,????.,,,.;,,,,.,;,,.,,,,.',,,.,;,
;,,,,,,;.,,,..,.,'.;';,.,,.";;,.;..,,,,,;,,,.,,.,;,,;,,.,.,",,;,,,.,,.
,,.,,,,,,,,.;;,,.,.,;,.,,.,,;';,,,,,..;.,,,,,,..;,;,,,.,',.,.,.,,.,.,.
,.,,,,,.;,.,,;,,,,,,,;,;.,;,!,,,.,,.!,;..!,!!.;,.,,.,,,.,,,',.,.,...,,
,;,:,,.',!,,.,,.,,:.;,,,,.;,,,.,?,..',,'''.,,;',..,.,.,',,.;,"";..',;,
;.';,';;,!,"","."!",,;.',,,.,,.,;,.,.';.';''.,,',;,..,,(;,.,;.'.,,;,,"
!,..,,;,,,,';,,..;,,,.,,;',,,,.,.;,,.,;,;,..",."!",."."!".,,.,;,.,,,,,
;;.,,,'.;,.,.',,;.,,.,.,,,',,,.,..;,,..,,",",;;.,,.,..,.,";,,.,,''""".
""'.;'',,',.,,.,.,;...'.?,',.,,,.,,;.'('.,,,..,;.;,.;.,,;;.,.,,;.,,,.'
,,.;.,.,..,.;.,.,,..,,.,.;,.,,,,,?,,,!;?!"",,,!??,",..",,?""',";.",,."
";,",.;.;''.,,,,,.;,;,,,.,,.,.,.,;,.,',,.;,,..,,,,,,,,.,,,',.,.,,.",."
",;?"",'''",,".?';!."'","""",,'"",,,,,.,,,''",",",,";?',,"";';'.",,,?"
""","',.,',;,'"";,,,,;,'."""",."',',.;;..,,;,,...,.;,,.',,,...;':?,.'.
,,,,,,',.,,.',.;.,,.,(,,,;,;.,;.,.,,';...;.,,,;.,;,.,;,,,,..,;,,..,,;,
..,.,,'';,..,',,.,!,.,,,,;,,,,;',,,.,,,;,,,,,.;;,.',''().',,,,,,,,",,,
,,",.,!!;.,.,.,,.,;,,,.,,,.,,',.,.,.":",,,..,".,'.,;;.,',,?,,,;;.,.;,;
;,.,;.',.,.,.?;,,,.,.;,,.,;,;,,.;;;.'.,,;..,;.,.,,,,'.,,,,...,,,;,;;;,
,.,.,;,;;;,;,..;?'..',,;.,,...,.,,,..,'.,,;,.,;.',,.,,,';,,,',;,.,,,,,
',,.,,,,.,.,.,.,.,,;,,.,,,,,,,.,,.,;.,;;,;;!,,,".,,.,,;.,;,,.,;.",;,,"
??,".,,;;',,!,.,.,.,.";;,",.,,,,,,,,,;,,..,,,;,.',','',,;..,,,,,,.,;;.
,,,,?,;.,.,,..,,;,.;;,.,,;.'!,,..,.,.,,.,..'.,.',;,.,,,.;,,,,.,'?,..,.
,;,,,;;,.',,''.,...,.;';,.,.,.,',..,,.(;,,,,,.',.',.,..,,,,.',.,..;,,,
.,;.',,'.,,',...,,,;,.,,,."."'?!"',,;.,;;,,;(.,';,.,,,,.,.,,,,,.,,.,,,
."','?,;,.,.",".,,,.',,,,.,."!"";',?''',",,,',,!,'.".'?",;.,,,!,,,.,,;
,,'',,,;.,,.,,,;;,;,.',,,,,;.!',.";..!!,'!!!'.;,;,,,,.,;;.,;,..;,!.,,,
;,;,!..?"?,,;!?,,',,'!",,.,,.",,,'.,.;,,;,.,,;,.,,,,,.,,,,,,,.,,.,,"".
,,,,.,,;;.,.,.,,.,,,.,,,,,.,.'..'',;,;,,..,,;,,."",;,.",.,,.,;.,.,;,..
,,!,.,;;.,,.;.,,,.';,,,..,,!.,;,,,.,,.,';,,,.;.;,,'.,.,,.;,",,,..,,;,,
;';.,,.,,,,,.,,.(,).,:,;,,,,.,;.?,.,.,,;;,,,,,,,;,,?,!?..,,;,':,'(),.,
'.'.;.(,',,,,,;"",,.,,',.??.,,,,,,.,.,,..'.,;;,;;.,,;,'..;,,,,;,.,,?,,
.,;,.;,,.,,;,,.;,.;,,,,,';,,..,,,";,!,'.,.;,.,;,,,(,,.,.,;,,..,,;.;,,,
,.,,..,,,;?,,,,.;,,,,.,,,,.,.;.,,,.,.,!,;,.;,;;,.,?.,,(,;,,,.!,,,;.;,,
,.;.,.,.,.?!;..,.;,,.,;,',',,..,,,,,,,.;;,,.,:,;,.,,,,;.,,.,;,,,.'.,,;
,,,.,;.',.,.,,.,.;,:,,,.,.,,,;.,,;..,,.,,.,,,;,,,.,,,'.;,:...,,..:,,,.
,..,,,,,',:;',;'!,',.;,.:,,.!,;,.:,;,,.'...;,,,.,,,,,.,,,,'',',.,;;,,.
,,,;.,.,,?,.,,,.,,.;.,;,,:,,,,,.,.,,,,.,,,.,;,,,,,,,,,;,;.??,,.,;,';.;
,,.,,,.;",,,;,,,,,,,.,,,,,.,,,;.,,.,,,.',,,,,,,;,;,.,,.,,!,,.,,;;,,;,,
,,;,,,,;.,,;,;,,.;,,;,.;,,,,,,,',,,,'.,,.,.,,..,.,',.,.,.:.,,',.,.,,,.
',,.,;.,.,;,,,,.,;,,,.,.",.,.,,,;,,.,.;,.,.,..,,,',,.,,;,.,,,.,.,..,,;
,,,.;.,;.,,,,..,;;,;,.,,.;;.,.,,.,,,;,.,,,.;,''."","",;,;,.,,...,,,;:,
;'.;,,,;,,;,.,,;,.,,.,.,,,,,,,,.,;,,,,,.,;;.;,,.;",,,!,.;,.,,',.,;,.;,
.,;,,,,.,,,.,,,.,,,,.,.;,.,....,,.,,.,,.,,,;,;,;,,.,,.'.,,.;,.,;,,;;,;
,;,,,,.,.,,,,,,,,.,..,;,.,,,,,;,..,,,.,,,.!,,,,,.,,;,,;,,,.,.,.''',..,
.:,,,.;,.;.,..,;(;,(,.,',,.,..,.';,;,,,,,'..,,,;,,;,.;.,.,,;,;,,.',.,?
''?,,?'(,?,,?,..,??????,",,,,,,.;,,,,,.,,.,,..;.,,,;,;,',,;,.,"""""'?"
"?"".""",.,,,.(,(',?...,.,,"'".',..;';,,.,",.,,,.."..,,.;,,,,,..;,.,;.
,,;.,.,."';;,,',,.!''',,;;,'.;,.,.,,;.,,.,,."",,;,"?".""""",,".,,"",."
,,"."',?,.";,'",.,.,.,,,,.',.,';.,,,.,.,,,.,';..,,.,,.""",",,.,"",.,",
,.,,.""'".,(.""'",,',,,'',.;,',,.,;,.'.,,,,,,,.",,,;;.,;,',,,.,,.,,,,,
,,,.,,!,,'',,',.;.;..,,.,,,,',,..?,,,;,,,,,,,,,,,.,,.,.;,,,,;,,,,;.,.,
,,?,';.,,.,',.,!,,,.,,;,,',;,,,,,',.,;,,,,..,,,,,;,,,,,,,,,,;,...,,,,"
.,.,,,,,,,,,;",',',.;;;,',,',.',.,.,..,?.?,,;,;;,.,,;,.;;,,,,;,,,.'.',
;..;.'',,,,,,,,,..!.!,,,;,,;,;,,;;;,.!;;',,;,,,!;.!,,,;,;.,.,,,,...'.,
,,.,,,,.,,.,.,,,,,.,,..,',,,.,,,,,,,'.,.,.;,'.;,,,';,,,.,;,,,.,,,.,,,,
,,,,.,.;,,,;;!!.,,,.,...,.,,.,.,,'.,.,,.,,,,.,,,.,..;.'.."...,,,.,,!,.
,;..;;,,,,.,,,,.,,,.,.,.,.,,.,;,,;,,;,,',.,,,,,.,..,,;.;,,.,.,,,!,',,,
!,!;,,,,,''.,.,,,'.',,,,,.,"",;,.,,',.,.,.,,''.,,.,,.,.;;;);,,,,,:.,;,
,,;,,,,,,.,.;';;;;.,!,,..,,,...,;,',;,.,,;.,..:,,.,;,,,,;,;,",!',;,,'!
,,,,,,,.,,;,,,.,,.,,,.,,,,,,,.;,',,..,;,,.:,;.';,,.,.",.,,,,.;.!!',,",
,".,,,.,,,,,,"".,'!;,,,,?!!,''.',:!'.!'.,',',;,,;,!,;,,;,,;.',,,',,,,,
.,",?,';";.,;;'.".;.;'..",.?,,,';,,,;,!,.""!"""""'.',.".,.".,'!,;?,.!'
!,",.,,,,;'"",."",,.,,,',',.,,;.,,,.,,;.,,!,,,,(,,,.,,,(",'",;",.""".,
;',,,".",",,"."";,',,,,()'(,,,,,',,,,,;,,,,,""',,;(),,,;,,.,'""",".;",
',,..''",".,;"";.",,;;.,;";,.,,,"".?,,"."'',.""""?.".",,'..;,,,;,,.,,,
",;',,'.",'?","!,"?""?,'''.,.,,,;,.,;(;(,:,;.,,,.;,,.,,,.,;,.".,,;.,.,
,,,,,.;(,;,,,,,.,;,;..,.',,.,',;.,,;,,.,.,;,,.,;,,,.,."..,.,";.,;.,,,,
,,,,.,;,,.,,,;,.,,,,.,,,,,,;,.,';,,,;.;;.,,.,;.,,,,;.,,?;,,,,;;,;,,;.,
,,,,?,,.,,;,,,;,,,,,,.,,.;,,;,..,',,,,..,??!;.,,.;,.,',,,,;.,,,,..,.,;
,.,;",',..,.,,,.,".,,',.;.',.;.;;.,,.,,;.',,..,';,,,;,.,,,,.;,,,.,:;.,
,,,.,,,,,.;,,..,..,,.,,.;..,,,,!,,,.;..,',.,,.,.,'',..,,.,;,.,,.,.,,,'
.,.?.',,,,,,.!,,.,,,,,;,,;,.,,.,,,,.,;,'.,,.,.,,,.,,.,,;,,;';;,''.'.,,
.,;,.,,.,,,,";.,,,,,',,'.,,.,,',,,.,(),.,,.,.,.,;,,,,!,(,,(,.?',.,,;,,
,',.;.,';;,,,.,,,,;,..,;;.,.,(,,,,,,(,,,,,,,,,,;,.:,.,,,,!,,.,'.,,,.,,
,,,,,.:,,.,,.,,;,.,,,.',..,(,,,,,.',,,,.,;;,..,,';,.,,.,;,,:,.,,,,,;,.
;,.,.,;,,.,,,';,,,.,,(,,,;.,;.,;.,.,'.,,;'.,,':,,,;,.,;,,.:,.,,.:;.:.,
;;,.,.;.,..;,;,.,,,;',,,?;.,;,,,;.,,;,,,,,,,,.,.,,,,.(,.,..,..((.,',.;
;,('',.,,,(,,,!!,,,;,,,.!,.,,;!.;.?;.,',;,,,?',,,.,?,??',,'?,,,;,?,,,,
,,;.,,;,,;,!',?,,,!.;,(.'.(,''.''',?'.,;',,.;,,',,!;',,;!.;.,,;,;,.,,.
;,,,,."."."?".,"""!,;';'."".,.;'",";"?",(',.,.,";,"!",;,,":,,,,;,,,,,,
;.,,.,,;,..,,.,;.,,;,.,!,;,,,;,.,.,,;,,.,.,,.,,,.,,,'.;.,,,,;,,;,,.,,.
,;,.,'.,,.,,,''".,,,.,,,.,',,,,,.,.,;;,,,,,,(,..,,;"?,?';..",,.,,,."?!
!;;''!,.!.,,;,',,,;,.,,,.,,,.(,,,,,,;,,,;;;;,,";,;.,;.',,,,.,.,,,,,';,
.',(;.,,.',",,,,',,;.,;,,..,..,,.;.,,,,,,,',',;,,,,,,'!,,,,',,,.,,,;,,
,.?;;;;;;;;;;,,,,;";,!,!,,,.,,,,,,,,";;";'"..?,?""?"",""',;,.""'!',",.
".".".,.,,",,,,,,,,".,,,,"""?",,,.",,;,.",?,,",.,,.,,,",;;',,,,.,.;,!.
,,,;,;,;,';.,,;,,'.;,,,;,,.,.,,,,.,:;,',,.,,,?:.,,",;.,:"!,,,,,,;;.,;;
.,;.,,,.;,,,,;;',.,;,,,.,;,,,,,,,.,',.,;,.".""."",,",,!,;,;.,,,.,,,.,.
;;;,,,,,.,,.",;.!;;,'!.";,,,,"!,,,;,".,;,.;;'',,'',,,,."?"";;.".."""",
?.""",,'.;,,,;'.,.,.'.;''.,,.,'',.;,.:"??.;,,,,:,;,,!;!;,,',.,;;.,!,,;
,,!;,,.,,";,,!",,;,!:.:.,..,.,.,,;..,,,,"",,,;!,',,''',,,,',,";.";,.'.
""?",,??,!"",".;.,,."";.,;,,;,,'',,.",..".,,";,,.",";!,,,;';.,;,.,.,;,
.;.,..",?,,;',,''.".",';,,,,,."!;;,;.",,,.'.;,,;,.,,,.,.,;.";;..;,.,,;
,;,.;,,,,,,,,!;"',';,'";,,,.'.,;',,:",:!.,,,'..,."."""".!.,.,!.!,.,.?'
,?",;?',.?,.,','',,,,.,'''""',.,.,,,,,,,.,',,!!,.."';,.,,,';.,,,.,;;,.
,,,;,!.,,,.,.,'.,.,.,,;.";.,.''.'.;.??,??'?,,.,??';..;???;;,;,.,,.,,,.
",!,,?!"',.',,"..,,,;.;.,,.,,','.".;,,""";;.,;.,.,,.,",,.,,,,,;,',;;.,
,,,';,.,,.,.;,'.,.",,.',,,.,,,",',,;.,,,,,.,,;,,,,,,,,,,.,.,.',,,,..,;
.,,,.;".",,,,,,.,,,."."'"''";?""""';,!.,,."!.".,,.".,,"',,!.!"""""".!"
;!"!,',.".'.;.".!!,.,""','''.,,;.,,,',,,,;,.,;..,,,,,,,...;(,,,,.,;,,,
,,;,,,,..;;,,;,.""".".,"""."".!.".;'?'.'',,,''!.';.!;,',.'!,,,.'',,,,,
;.,;.!"!"""?"""'",,?.""?;.",."',,"""'"""!".,,.',,("!!,!,'.,!,,,;,!!,,;
,,.",,"",,,.'.."",',,,;.,,.;;,,;,.,;.;;;;.,.;,."''?'"",.,,"?.";,,'',,,
;',,,,','.,,''',,,.".,,."",,;,,,.,;.;,,;;,,.,,,(,,..,,.;";."!;",.,";""
,.!.,(",!'':,,,,!;,!,;,..,';,,,;;;,'.,''.,,.,,.,,,';'',,;;,',,;.,,,,,,
;,;,;;,.,;;.;:;,.;;.;,;,,;;,.,,;,;,,,,'!,;',,.,.".;,,;,,,,;,,,;,,,.,,,
.,;,,,.',,;;',;;.;,,;,.",,.':.',..;;,.;;,,,;,',,,""."",,.",!;,"";;.?;"
";,.,'""!.;,,',;,,,,;,,;,,,;;;;',!!!,.,,.,,,,,,.;.;.,,."""!!,!!,.;',!,
!,',,?,,,!'?,?,?,!,,.!;!;.,,.,"!!,,,!,!,".;,.",'!!'',",;,,??;;;,,.!?',
,,.,;!';,.,,,'.,,,,,,,,,,,",,.""",;,,,.!,.,,',,..".","..!,'!.,!,.";"!'
;.;,.;,,,,,.,;;.,,',,.,.;,,;.,,,.,,.,,,,;,',..,,"'..;",',,',,,,,'.;.,,
.,,.,,.;,,,.'..,'.,;,,;,,;,,,,,,,,,.,';.',,.,,;;,,.,..(,..,;,.'.',;.';
;',,,,;,,,;,,.,'.,';''',..,',,,,."""""."!!;,,..,;,,,;..,,,,.,;,,,'.,,,
,,,;,.;,'"!",(.",",';;,!'!;,"""",;!..";,,,!,,.,".""!',,.,;,,.,,;,,:;,,
,.,.,',;,;,.,'?,.;,."'!,,".",!!.,;,.;;,;.,;.,,;,;,,..,,;,,!!",",;,;,.,
,!;,;,,.,,".,,,."!!,,;.".,,,.,,,',',,,,.;;'.,,,,;,,!!,,'.,,,;,;;,,,,.,
,,;;';,',,,,.,;,;,,,,,',,,,,;;.,'',,,";"."",,'.,!"".'""!"".!'."",.".",
.';!!!!,";';;:???!"',,,'.,;.',;,,!;','"":,'!'':',,;,.;,,.,,."";!,,',!,
,,,,;,.;.,.,''.,,.;,,,,.,,,,.;,,'""!,''!!,'.",".!""".;.,,."!'!.;;,.!,!
.!.',,.'.'?,',,,',;.;',.""""","";,;";""."";.;,,;.;.;',.""?,?;,.!,,.;.'
;,,':!"!!,,,;,."!:!;,,;,,,;,,.";.,,;,';,;.,,;;."..?;,,,';,,;,,,.",,,,,
',,,;,,,.;..,,,';:,,'.;,,."!"""?!.,',';,,,,,,,.,,;,,,,,.,,,!"!,;,;;,.;
!'"",!?,,;,.,;,,,.",'?,!,,";!';,.,!!;,,",,',,,,.,,'..,."",,,.".;,,?,,,
,;'!,,;;;,,,,.,",;,.,,.,,,;,.,;;,,,,,,.;;.".'.,';,.,,,,,.;,,.,,;,,,(,.
,.;",,,";'";',,,,,,,,,,,,(,,.,,,,',,,,;,;,,,!;,,,!".".."."..",;"',.'",
.'",,,.'",.,..',"',,.".."'".'"..."..".",','."..",.."..'.'"('".'",..",,
;,.".'",,.'",;'",..".'".',,..,",)..'",,'"'.",.'",'",,'.",..,"..",.,'",
,,.'.",'"'".",.,."','",.",,.,",'",''".",'.",,,;:',,,,'"';,.'",'.'",'",
.".'".'".",.,,";,,..",.",..";,;,.,(,,,.'"",,.'.""""""!""!""".",.",;;..
.".,.'."."'..".(,.",,.'";."".,,..",,..",.."(.."..",..",'.'",!."!.",..

Feel free to experiment with extract_punct() and let me know how it goes. Maybe include en and em dashes, or take a look at the use of ‘curly’ quotes, or something.


Session info
─ Session info ───────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 4.1.0 (2021-05-18)
 os       macOS Big Sur 10.16         
 system   x86_64, darwin17.0          
 ui       X11                         
 language (EN)                        
 collate  en_GB.UTF-8                 
 ctype    en_GB.UTF-8                 
 tz       Europe/London               
 date     2021-09-12                  

─ Packages ───────────────────────────────────────────────────────────────────
 package     * version date       lib source        
 assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.1.0)
 bit           4.0.4   2020-08-04 [1] CRAN (R 4.1.0)
 bit64         4.0.5   2020-08-30 [1] CRAN (R 4.1.0)
 blogdown      1.4     2021-07-23 [1] CRAN (R 4.1.0)
 bookdown      0.23    2021-08-13 [1] CRAN (R 4.1.0)
 bslib         0.2.5.1 2021-05-18 [1] CRAN (R 4.1.0)
 cli           3.0.1   2021-07-17 [1] CRAN (R 4.1.0)
 crayon        1.4.1   2021-02-08 [1] CRAN (R 4.1.0)
 curl          4.3.2   2021-06-23 [1] CRAN (R 4.1.0)
 DBI           1.1.1   2021-01-15 [1] CRAN (R 4.1.0)
 digest        0.6.27  2020-10-24 [1] CRAN (R 4.1.0)
 dplyr       * 1.0.7   2021-06-18 [1] CRAN (R 4.1.0)
 ellipsis      0.3.2   2021-04-29 [1] CRAN (R 4.1.0)
 evaluate      0.14    2019-05-28 [1] CRAN (R 4.1.0)
 fansi         0.5.0   2021-05-25 [1] CRAN (R 4.1.0)
 generics      0.1.0   2020-10-31 [1] CRAN (R 4.1.0)
 glue          1.4.2   2020-08-27 [1] CRAN (R 4.1.0)
 gutenbergr  * 0.2.1   2021-06-01 [1] CRAN (R 4.1.0)
 hms           1.1.0   2021-05-17 [1] CRAN (R 4.1.0)
 htmltools     0.5.1.1 2021-01-22 [1] CRAN (R 4.1.0)
 jquerylib     0.1.4   2021-04-26 [1] CRAN (R 4.1.0)
 jsonlite      1.7.2   2020-12-09 [1] CRAN (R 4.1.0)
 knitr         1.33    2021-04-24 [1] CRAN (R 4.1.0)
 lazyeval      0.2.2   2019-03-15 [1] CRAN (R 4.1.0)
 lifecycle     1.0.0   2021-02-15 [1] CRAN (R 4.1.0)
 magrittr      2.0.1   2020-11-17 [1] CRAN (R 4.1.0)
 pillar        1.6.2   2021-07-29 [1] CRAN (R 4.1.0)
 pkgconfig     2.0.3   2019-09-22 [1] CRAN (R 4.1.0)
 purrr         0.3.4   2020-04-17 [1] CRAN (R 4.1.0)
 R6            2.5.1   2021-08-19 [1] CRAN (R 4.1.0)
 Rcpp          1.0.7   2021-07-07 [1] CRAN (R 4.1.0)
 readr         2.0.1   2021-08-10 [1] CRAN (R 4.1.0)
 rlang         0.4.11  2021-04-30 [1] CRAN (R 4.1.0)
 rmarkdown     2.10    2021-08-06 [1] CRAN (R 4.1.0)
 rstudioapi    0.13    2020-11-12 [1] CRAN (R 4.1.0)
 sass          0.4.0   2021-05-12 [1] CRAN (R 4.1.0)
 sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 4.1.0)
 stringi       1.7.3   2021-07-16 [1] CRAN (R 4.1.0)
 stringr     * 1.4.0   2019-02-10 [1] CRAN (R 4.1.0)
 tibble        3.1.3   2021-07-23 [1] CRAN (R 4.1.0)
 tidyselect    1.1.1   2021-04-30 [1] CRAN (R 4.1.0)
 triebeard     0.3.0   2016-08-04 [1] CRAN (R 4.1.0)
 tzdb          0.1.2   2021-07-20 [1] CRAN (R 4.1.0)
 urltools      1.7.3   2019-04-14 [1] CRAN (R 4.1.0)
 utf8          1.2.2   2021-07-24 [1] CRAN (R 4.1.0)
 vctrs         0.3.8   2021-04-29 [1] CRAN (R 4.1.0)
 vroom         1.5.4   2021-08-05 [1] CRAN (R 4.1.0)
 withr         2.4.2   2021-04-18 [1] CRAN (R 4.1.0)
 xfun          0.25    2021-08-06 [1] CRAN (R 4.1.0)
 yaml          2.2.1   2020-02-01 [1] CRAN (R 4.1.0)

[1] /Library/Frameworks/R.framework/Versions/4.1/Resources/library

  1. Readers may remember {crayon} from my recent post about the {dehex} package.↩︎

  2. In particular, it’s easy to print the character vector of punctuation characters and linebreak it with the fill argument of cat(), but this behaviour is altered when you convert the characters to {crayon} strings. Instead, extract_punct() inserts newline characters at the desired print width using a crummy trick that flattens a matrix of the punctuation characters. Of course, matrices are ‘square’, so there are leftover punctuation characters that have to be dealt with separately and pasted on to the end, lol.↩︎

  3. No, not the legendary San Antonio Spurs center from the 90s.↩︎

  4. I think I first learnt about this from Carl Sagan.↩︎

  5. Note that you can use gutenberg_works() for a pre-filtered dataset with English-only texts, are in text format and whose text is not under copyright.↩︎