10
\$\begingroup\$

Write a program that accesses Project Gutenberg's KJV Bible, either from a file called pg10.txt in the working directory or in any other way that is typical for the language, takes a Bible verse reference as input, and prints the corresponding verse, with no newlines except optionally one at the end, as output.

The standard format for a reference is [book] [chapter]:[verse], e.g. John 3:13. However, some books have only one chapter. For these books, the format is [book] [verse], e.g. Jude 2. Your program must accept this format for single-chapter books. Behavior when using the standard format with single-chapter books, or when using the single-chapter format with multi-chapter books, is undefined.

Note that the "title" for the book of Psalms, for the purposes of this question, is Psalm, not Psalms, because references are usually written like Psalm 119:11, not Psalms 119:11.

Use the following titles for books of the Bible. Single-chapter books are in italics.

  • Genesis
  • Exodus
  • Leviticus
  • Numbers
  • Deuteronomy
  • Joshua
  • Judges
  • Ruth
  • 1 Samuel
  • 2 Samuel
  • 1 Kings
  • 2 Kings
  • 1 Chronicles
  • 2 Chronicles
  • Ezra
  • Nehemiah
  • Esther
  • Job
  • Psalm
  • Proverbs
  • Ecclesiastes
  • Song of Solomon
  • Isaiah
  • Jeremiah
  • Lamentations
  • Ezekiel
  • Daniel
  • Hosea
  • Joel
  • Amos
  • Obadiah
  • Jonah
  • Micah
  • Nahum
  • Habakkuk
  • Zephaniah
  • Haggai
  • Zechariah
  • Malachi
  • Matthew
  • Mark
  • Luke
  • John
  • Acts
  • Romans
  • 1 Corinthians
  • 2 Corinthians
  • Galatians
  • Ephesians
  • Philippians
  • Colossians
  • 1 Thessalonians
  • 2 Thessalonians
  • 1 Timothy
  • 2 Timothy
  • Titus
  • Philemon
  • Hebrews
  • James
  • 1 Peter
  • 2 Peter
  • 1 John
  • 2 John
  • 3 John
  • Jude
  • Revelation
Reference Text
Genesis 1:1 In the beginning God created the heaven and the earth.
1 Samuel 1:1 Now there was a certain man of Ramathaimzophim, of mount Ephraim, and his name was Elkanah, the son of Jeroham, the son of Elihu, the son of Tohu, the son of Zuph, an Ephrathite:
1 Kings 1:1 Now king David was old and stricken in years; and they covered him with clothes, but he gat no heat.
Psalm 119:11 Thy word have I hid in mine heart, that I might not sin against thee.
John 3:16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life.
1 John 1:9 If we confess our sins, he is faithful and just to forgive us our sins, and to cleanse us from all unrighteousness.
3 John 1 The elder unto the wellbeloved Gaius, whom I love in the truth.
Jude 21 Keep yourselves in the love of God, looking for the mercy of our Lord Jesus Christ unto eternal life.
Revelation 21:11 Having the glory of God: and her light was like unto a stone most precious, even like a jasper stone, clear as crystal;
Revelation 21:16 And the city lieth foursquare, and the length is as large as the breadth: and he measured the city with the reed, twelve thousand furlongs. The length and the breadth and the height of it are equal.
Revelation 22:20 He which testifieth these things saith, Surely I come quickly. Amen. Even so, come, Lord Jesus.
Revelation 22:21 The grace of our Lord Jesus Christ be with you all. Amen.
\$\endgroup\$
18
  • 1
    \$\begingroup\$ @Seggan I could maybe say that it must take either two or three inputs, three being the standard format and two being the single-chapter-book format? That might not work in all languages, though. I was thinking of having part of the challenge be to parse the variable-format string, so I don't want to loosen that part too much. \$\endgroup\$
    – Someone
    Nov 21, 2023 at 3:03
  • 2
    \$\begingroup\$ Recommended test cases: 1 Samuel 1:1, 1 Kings 1:1. \$\endgroup\$
    – Arnauld
    Nov 21, 2023 at 10:43
  • 3
    \$\begingroup\$ @matteo_c there are four books with John in the title. "John" is the Gospel of John, and 1, 2, and 3 John are the First, Second, and Third Epistles of John. 2 John and 3 John are single chapter books; the Gospel of John and the First Epistle of John have multiple chapters. \$\endgroup\$
    – Someone
    Nov 21, 2023 at 16:50
  • 3
    \$\begingroup\$ @Seggan I would think that if I had created a new format for references, but since this is the way Bible references are normally written, I was thinking of it as part of the challenge. I'm also not sure how the part about single-chapter books would work while allowing pre-parsed input. \$\endgroup\$
    – Someone
    Nov 21, 2023 at 17:40
  • 2
    \$\begingroup\$ Some languages don't have a concept of reading files from the working directory. I'd suggest allowing the Project Gutenberg file to be supplied in whatever way a language normally takes input. For some languages, that will be as a filename command-line argument. For others, it will be the entire contents of the file as a command-line argument. For others, it may be via STDIN. \$\endgroup\$ Nov 21, 2023 at 17:47

3 Answers 3

5
\$\begingroup\$

GNU sed -En:  330 321 303 298  283 bytes

The reference is given in the first line. In real life you can do this like sed 'the script' <<(echo Luke 19:10;cat pg10.txt)

1{s/^([123]) /\1/;s/.* S/S/;/:/!s/ / 1:/;h}
/\n/!N;N;/^.{5}$/!D;n;n;s/\r//;/Bi/D
/Ac|La|Re/s/ of.*// 
s/The Fi/1/;s/The Se/2/;s/The Th/3/;s/^[123].*M//
s/[^0-9]* //;s/ms$/m/;G;/^(..*)\n\1/!d
:1
n;G;/(.*:.*) .*\n.* \1$/!b1
s/\n.*//;s/.*[0-9]:\S* //
:2
N;/ *[0-9]*[:*]\S.*/!b2
s///;s/\r\n/ /gp

Explanation: The first line forms the given verse to remove the whitespace after a number, rename the Song of Salomon and add 1: for one-chapter books; this gets saved in the hold space. The second line finds book titles, the following three convert them to a canonical form and check for a match with the given verse. The rest of the script search for the exact verse inside the book and strip it to only that verse.

This was the original POSIX sed -n version with 298 bytes:

1{s/^\([123]\) /\1/;s/.* S/S/;/:/!s/ / 1:/;h;}
/\n/!N;N;/^.....$/!D;n;n;s/^M//;/Bi/D
/[ALR][cae]/s/ of.*//
s/The F/1/;s/The Se/2/;s/The T/3/;s/^[123].*M//
s/[^0-9]* //;s/ms$/m/;G;/^\(..*\)\n\1/!d
:1
n;G;/\(.*:.*\) .*\n.* \1$/!b1
s/\n.*//;s/.*[0-9]:[^ ]* //
:2
N;/ *[0-9]*[:*][^ ].*/!b2
s///;s/^M\n/ /g;p
\$\endgroup\$
2
  • \$\begingroup\$ Revelation 22:20 isn't the only verse with a blank line inside, it's just the first one I noticed. Others include Revelation 21:16 and John 8:52. I assume it's something weird with the Project Gutenberg version rather than a standard feature of the KJV... \$\endgroup\$
    – DLosc
    Nov 21, 2023 at 22:17
  • \$\begingroup\$ @DLosc Thank you. So I changed to a more general solution, always reading up to the next verse, which required some extra handling of Rev 22:21, but saved some bytes in the end. \$\endgroup\$
    – Philippos
    Nov 21, 2023 at 22:41
4
\$\begingroup\$

JavaScript (ES6), 216 bytes

Expects (text)(reference).

t=>s=>([,s,v]=s[M='match'](/(.+) (.+)/),t.split(/\*+|[\r\n]{10}/)[(n=t.split`
`.findIndex(r=>r[M](s.replace(/\d/,n=>` ${"_FST"[n]}.* .*`))))?n-21:64]+0)[M]((v[1]?v:"1:"+v)+"([^]*?)\\d")[1].trim().replace(/\r\n/g," ")

Try it online!

(The TIO code works on a small extract of the original file.)

Method

  1. We compute the book number by looking for the line containing the book name in the summary. There's a special case for James which appears on the very first line of the file. We also have to be careful about the misalignment between Malachi and Matthew.
  2. We split the text and extract the relevant book.
  3. We look for the requested verse in this book and format it.

Commented

t =>                    // t = input text
s =>                    // s = reference
(                       //
  [, s, v] = s.match(   // split s into:
    /(.+) (.+)/         //   s = book name
  ),                    //   v = "chapter:verse" or just "verse"
  t.split(              // turn t into an array of books
    /\*+|[\r\n]{10}/    // by splitting on "***" or "\r\n" * 5
  )[(                   //
    n = t.split`\n`     // split t on new lines
      .findIndex(r =>   // and find the first string r
        r.match(        //   which contains:
          s.replace(    //     the book name
            /\d/, n =>  //       with the leading digit (if any)
            " " +       //       replaced with a space
            "_FST"[n] + //       followed by "F", "S" or "T"
                        //       (for "First", "Second", "Third")
            ".* .*"     //       followed by ".* .*"
          )             //     end of replace()
        )               //   end of match()
      )                 // end of findIndex()
  ) ?                   // if n is not 0:
    n - 21              //   use n - 21
  :                     // else:
    64                  //   use 64 for "James"
  ] + 0                 // get the n-th book and append a "0"
).match(                // then find:
  (v[1] ? v : "1:" + v) //   the verse header,
  + "([^]*?)"           //   followed by the verse content,
  + "\\d"               //   followed by a trailing digit
)[1]                    // end of match(); keep the content
.trim()                 // trim it
.replace(/\r\n/g, " ")  // and turn line breaks into spaces
\$\endgroup\$
0
4
\$\begingroup\$

Jelly, 80 # Jelly, 66 bytes

ḢfØDV+2ị=”JƲo1
Ḳ-ị⁹œṣ⁷x5¤¤ỴḢwɗƇị@Ç{ỴKḲ<”AȦ$€œṗ$Ḣ⁼¥ƇḲṪ¹⁾1:;$f?”:ʋḢK

Try it online!

A pair of links that is called as a dyad and that takes the pg10.txt file as its right argument and the required biblical reference as its left argument. TIO fails with the full document (presumably because the POST exceeds the maximum size), and the links to TIO on CGCC are even more limited because of length. However, it should work with the full text if run locally.

Pleasingly now code length in bytes == number of books in bible.

Explanation (outdated)

ḢfØDV+2ị=”JƲo1                                          # Helper link: Takes a bible reference and returns which number book should be used that matches the textual part of the reference; half the code is to handle the John letters
Ḣ                                                       # Head
 fØD                                                    # Keep only digits
    V                                                   # Evaluate (will be 0 if no digits)
     +     Ʋ                                            # Add the result of the following, applied to the helper link's original argument
      2ị=”J                                             # - 1 if the second remaining character is a J, otherwise 0
            o1                                          # Or 1 (replaces 0s with ones)

Ḳ-ị⁹œṣ”¶x5¤¤Ỵ€¤Ḣw¥Ƈị@Ç{KœṣḲṪ¹⁾1:;$f?”:ʋ2ịwⱮØD;€”:¤œPƊḢḊ # Main link: takes a bible reference as its argument and returns the verse
Ḳ                                                       # Split at spaces
 -ị                                                     # Penultimate part (will be the last word of the book title)
   ⁹          ¤                                         # Using the following applied to the right argument:
    œṣ”¶x5¤¤                                            # - Split at five consecutive newlines
            Ỵ€                                          # - Split each at newlines
               Ḣw¥Ƈ                                     # Keep those where the first line includes the book title word from earlier
                   ị@Ç{                                 # Index into this using the result of calling the helper link on the original reference (so returning a single book)
                       K                                # Join with spaces
                        œṣ            Ʋ                 # Split at the substring determined by calling following on the original reference:
                          Ḳ                             # - Split at spaces
                           Ṫ                            # - Tail (i.e. the verse or chapter:verse)
                                  f?”:                  # - If contains a colon:
                            ¹                           #   - Leave as is
                             ⁾1:;$                      #   - Else: prepend "1:"
                                       2ị               # Take the second part (i.e. the bit immediately after the chapter:verse reference)
                                                    Ɗ   # Following as a monad:
                                         wⱮØD;€”:¤      # - Find the position of every sublist that comprises of a digit followed by a colon
                                                  œP    # - And split at these
                                                     ḢḊ # Take the first remaining part, and then remove the first character (which will be the space left just after the original chapter:verse marker)
💎

Created with the help of Luminespire.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.