17
\$\begingroup\$

Introduction:

I have loads of different ciphers stored in a document I once compiled as a kid, I picked a few of the ones I thought were best suitable for challenges (not too trivial, and not too hard) and transformed them into challenges. Most of them are still in the sandbox, and I'm not sure yet whether I'll post all of them, or only a few. Here is the third and easiest one (after the Computer Cipher and Trifid Cipher I posted earlier).


With a Clock Cipher we use the following image to encipher text:

enter image description here
So a sentence like this is a clock cipher would become:

t  h i s     i s     a     c l  o  c k     c i p  h e r    (without additional spaces of course, but added as clarification)
19:7:8:18:00:8:18:00:AM:00:2:11:14:2:10:00:2:8:15:7:4:17

Challenge:

Given a string sentence_to_encipher, encipher it as described above.

Challenge rules:

  • You can assume the sentence_to_encipher will only contain letters and spaces.
  • You can use either full lowercase or full uppercase (please state which one you've used in your answer).
  • You are not allowed to add leading zeros for the single-digit enciphered letters b through j, but two zeros 00 are mandatory for spaces.
  • You should use : as separator, and an additional leading or trailing : is not allowed.
  • You are allowed to use lowercase am and pm instead of uppercase AM and PM, as long as it's consistent.

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code (i.e. TIO).
  • Also, adding an explanation for your answer is highly recommended.

Test cases:

Input:  "this is a clock cipher"
Output: "19:7:8:18:00:8:18:00:AM:00:2:11:14:2:10:00:2:8:15:7:4:17"

Input:  "test"
Output: "19:4:18:19"

Input:  "what time is it"
Output: "22:7:AM:19:00:19:8:12:4:00:8:18:00:8:19"

Input:  "acegikmoqsuwy bdfhjlnprtvxz"
Output: "AM:2:4:6:8:10:12:14:16:18:20:22:24:00:1:3:5:7:9:11:13:15:17:19:21:23:PM"

Input:  "easy peazy"
Output: "4:AM:18:24:00:15:4:AM:PM:24"
\$\endgroup\$
4
  • \$\begingroup\$ Related \$\endgroup\$ Commented Jan 4, 2019 at 7:40
  • \$\begingroup\$ Is it allowed to output [7, ":", 8, ":", "00", ":", 1, ":", 14, ":", 1] for hi bob, or must one join the result? By the way, neat cipher! \$\endgroup\$
    – Mr. Xcoder
    Commented Jan 4, 2019 at 9:27
  • \$\begingroup\$ @Mr.Xcoder Sorry, for the sake of the cipher theme I'd say it should be joined to a single string (or the entire thing as a list of characters like ['7', ':', '8', ':', '0', '0', ':', '1', ':', '1', '4', ':', '1']). \$\endgroup\$ Commented Jan 4, 2019 at 9:32
  • \$\begingroup\$ @KevinCruijssen there might be a built-in to concatenate lists. \$\endgroup\$ Commented May 1, 2023 at 16:56

19 Answers 19

7
\$\begingroup\$

Python 2, 74 72 bytes

lambda s:':'.join(['AM','PM','00',`ord(c)-97`]['az '.find(c)]for c in s)

Try it online!

Takes input as all lowercase

\$\endgroup\$
6
\$\begingroup\$

05AB1E, 22 21 bytes

„AM24L„PM00)˜Að«s‡':ý

Try it online! or as a Test Suite

Some alternate 21 byte solutions:

':ýAð«24L„AMš„PMª00ª‡
00„AM24L„PM)˜AIk>è':ý
\$\endgroup\$
11
  • \$\begingroup\$ Nice answer, I managed to get 23 bytes through multiple approaches (one of which was my currently deleted answer). That's a neat way to arrange your stack to save a byte! \$\endgroup\$
    – Mr. Xcoder
    Commented Jan 4, 2019 at 9:41
  • 1
    \$\begingroup\$ An alternate 22 byter combining our answers: Try it Online! \$\endgroup\$
    – Mr. Xcoder
    Commented Jan 4, 2019 at 9:43
  • \$\begingroup\$ @Mr.Xcoder: My first idea actually looked like that, but 2 bytes worse because I didn't remember that ª had changed :) \$\endgroup\$
    – Emigna
    Commented Jan 4, 2019 at 9:48
  • \$\begingroup\$ I've found a 20 byter using a portion of @Mr.Xcoder's approach, but I'll let you figure it out yourself before I reveil it. :) \$\endgroup\$ Commented Jan 4, 2019 at 10:57
  • 1
    \$\begingroup\$ @KevinCruijssen: I'll let you know after I've looked some more ;) \$\endgroup\$
    – Emigna
    Commented Jan 4, 2019 at 13:39
5
\$\begingroup\$

Perl 6, 47 bytes

*.ords>>.&{<<00 AM{1..24}PM>>[$_%32]}.join(":")

Try it online!

Anonymous Whatever lambda that takes a string of either case and returns the encrypted string.

Explanation:

*.ords>>.&{                         } # Map the ordinal values to
           <<              >>[$_%32]  # The index in the list
              00 AM{1..24}PM  # 00, AM, the numbers 1 to 24 and PM
                                     .join(":")   # And join with colons
\$\endgroup\$
5
\$\begingroup\$

C# (Visual C# Interactive Compiler), 70 bytes

s=>string.Join(":",s.Select(a=>a<33?"00":a<66?"AM":a>89?"PM":a%65+""))

Takes input as a string of lowercase letters. First checks if the char is a space, and if it is, converts it to 00. Next, it checks for if the char is an A, and converts it to AM. It checks again for Z and converts it to PM if it is. Lastly, if the char passes all the checks, it gets converted to its alphabetic order-1.

-2 bytes thanks to @dana

Try it online!

// Input taking a string
s => 
// Join the following IEnumerable<char> with a ":" character
string.Join(":", 
// Map all the characters in the string
s.Select(a => 
// Is the char less than 33, aka a space?
a < 33 ? 
// If so, it's a "00"
"00" 
// Else, is this an 'A'?
: a < 66 ?
// If so, convert it to "AM"
"AM" : 
// If it's not 'A' or a space, could it be a 'Z'?
a > 89 ?
// If it is, turn the character into "PM"
"PM" : 
// If it fails all of the checks above, get the characters position in the alphabet and subtract one from that.
a % 65 + ""))
\$\endgroup\$
0
5
\$\begingroup\$

Java (JDK), 86 bytes

s->"".join(":",s.map(c->c<33?"00":c<66?"AM":c>89?"PM":c-65+"").toArray(String[]::new))

Try it online!

Credits

  • -1 byte thanks to Kevin Cruijssen
\$\endgroup\$
2
  • \$\begingroup\$ One easy golf: char to var. :) \$\endgroup\$ Commented Jan 4, 2019 at 11:00
  • \$\begingroup\$ Thanks! So obvious now that you show it to me... \$\endgroup\$ Commented Jan 4, 2019 at 11:02
4
\$\begingroup\$

Pyth, 25 bytes

j\:m@+++"AM"S24"PM""00"xG

Try it online here, or verify all the test cases at once here.

j\:m@+++"AM"S24"PM""00"xGdQ   Implicit: Q=eval(input()), G=lowercase alphabet
                              Trailing dQ inferred
            S24               [1-24]
       +"AM"                  Prepend "AM"
      +        "PM"           Append "PM"
     +             "00"       Append "00" - this is the dictionary
   m                      Q   Map each element of Q, as d, using:
                       xGd      Get the index of d in G, -1 if not present (i.e. space)
    @                           Get the element from the dictionary at the above index
j\:                           Join the result on ":", implicit print
\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js),  72  65 bytes

Takes input in lowercase.

s=>[...Buffer(s)].map(c=>c<33?'00':c>121?'PM':c-97||'AM').join`:`

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Ruby, 49 bytes

->a{a.map{|c|["00",:AM,*1..24,:PM][c.ord%32]}*?:}

Try it online!

Port of Jo King's Perl answer. Takes input as an array of chars, returns a string with AM/PM in uppercase.

\$\endgroup\$
3
\$\begingroup\$

Red, 124 121 110 109 bytes

func[s][replace/all form collect[forall s[keep switch/default
c: -97 + s/1[0['AM]25['PM]-65["00"]][c]]]sp":"]

Try it online!

\$\endgroup\$
3
\$\begingroup\$

05AB1E, 20 bytes

':ýð00:A24L„AMš„PMª‡

Greatly inspired by @Mr.Xcoder's 22-byter in the comment of the existing 05AB1E answer by @Emigna.

Takes the input as a list of lowercase characters (would be 21 bytes with a leading S if I take the input as a string).

Try it online or verify all test cases.

Explanation:

':ý            '# Join the (implicit) input list of characters by ":"
                #  i.e. ["e","a","s","y"," ","p","e","a","z","y"] → "e:a:s:y: :p:e:a:z:y"
ð00:            # Replace all spaces " " with "00"
                #  i.e. "e:a:s:y: :p:e:a:z:y" → "e:a:s:y:00:p:e:a:z:y"
A               # Push the lowercase alphabet
 24L            # Push a list in the range [1,24]
    „AMš        # Prepend "AM" at the start of this list
        „PMª    # And append "PM" at the end of the list
            ‡   # Transliterate; mapping letters to the list-items at the same indices
                # (and output the result implicitly)
                #  i.e. "e:a:s:y:00:p:e:a:z:y" → "4:AM:18:24:00:15:4:AM:PM:24"
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Ah yes. Replacing the space separately saves a byte. I should have tried that. Nice :) \$\endgroup\$
    – Emigna
    Commented Jan 4, 2019 at 14:41
3
\$\begingroup\$

Charcoal, 26 bytes

UB:Fθ«→≡ι ×0²a¦AM¦z¦PMI⌕βι

Try it online! Link is to verbose version of code. Takes input in lower case (can trivially be changed to upper case). Explanation:

UB:

Set the background character to :. This fills in the gaps between the output values created by the right movement.

Fθ«→

Loop over each character, leaving a gap each time. (The first move has no effect as the canvas is still empty at this point.)

≡ι ×0²a¦AM¦z¦PM

Switch on the character and if it's space, a or z then output the appropriate code. I use ×0² instead of 00 here as the latter would cost two bytes in additional separators.

I⌕βι

Otherwise output the letter's 0-indexed position in the lower case alphabet as a string.

\$\endgroup\$
3
\$\begingroup\$

Perl 5 -pl, 46 bytes

s/./("00",AM,1..24,PM)[ord($&)%32].":"/ge;chop

Case doesn't matter. To run as perl -ple '<code>'. -l option passed to perl allows to drop the last colon with chop.

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Scala, 69 bytes

_.map(_.-(64)%32)map "00"+:"AM"+:1.to(24).map("".+):+"PM"mkString ":"

Try it in Scastie!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ 69 bytes. Very nice \$\endgroup\$
    – lyxal
    Commented Apr 8, 2021 at 3:07
3
\$\begingroup\$

PowerShell, 72 69 63 bytes

$(switch($args){a{'AM'}z{'PM'}' '{'00'}default{$_-97}})-join':'

Try it online!

Takes a lowercase string and does not add a leading 0.

The string is passed to the function using splatting.

It iterates through all the characters of the string, replacing them with their encoded values.

The resulting items are then joined using ':' as separator.

-6 bytes thanks to mazzy !

\$\endgroup\$
1
2
\$\begingroup\$

Tcl, 100 bytes

proc C s {join [lmap c [split $s ""] {scan $c %c v
expr $v==65?"AM":$v==90?"PM":$v==32?00:$v-65}] :}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

C# (Visual C# Interactive Compiler), 98 bytes

s=>string.Join(':',s.Select(c=>"az ".Contains(c)?new[]{"AM","PM","00"}["az ".IndexOf(c)]:c-97+""))

Takes input as a (lowercase) char array. Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ 82 bytes: s=>string.Join(':',s.Select(c=>new[]{c-97+"","AM","PM","00"}["az ".IndexOf(c)+1])). \$\endgroup\$
    – dana
    Commented Jan 5, 2019 at 12:45
2
\$\begingroup\$

Jelly, 24 bytes

«"⁾PMµØAḊiȯ⁾00µe?€⁾AZj”:

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Vyxal, 31 22 bytes

øA‹u025"J`00ṙ§m`2ẇĿ\:j  

Thanks to @lyxal!
I'm not familiar with Vyncode so just classic version.
Try it Online!

Explanation:

øA                      # Convert letter to number (space=0 and vectorized by default)
  ‹                     # Increment (vectorized)
   u025                 # Push -1, 0 and 25
       "                # Pair top two items (0 and 25)
        J               # Join -1  (so "J shorter than 3¨ẇ)
         `00ṙ§m`        # This uncompressed to `00ampm` (how?)
                2ẇ      # Split into 2-chunks
                  Ŀ     # Transliterate: replace each item of one value in another value with the corresponding element from a third value 
                   \:j  # Join by ":"

Old version for compare:

C97-⟨65N|0|25⟩⟨‛00|‛AM|‛PM⟩Ŀ\:j

Try it Online!

\$\endgroup\$
6
  • 3
    \$\begingroup\$ Ask, and you shall recieve: Try it Online! for 18.75 bytes \$\endgroup\$
    – lyxal
    Commented May 2, 2023 at 0:32
  • 3
    \$\begingroup\$ @lyxal Maybe it's also a good idea to explain how you've compressed them, so lesobrod (or others reading this) know how to do so for future challenges. :) \$\endgroup\$ Commented May 2, 2023 at 7:18
  • \$\begingroup\$ @KevinCruijssen In general, I figured out myself and will soon write a clarification \$\endgroup\$
    – lesobrod
    Commented May 2, 2023 at 8:10
  • \$\begingroup\$ @lyxal The only thing I don’t understand is how simple string 00ṙ§m uncompressed to 00ampm without « « \$\endgroup\$
    – lesobrod
    Commented May 2, 2023 at 8:50
  • 2
    \$\begingroup\$ 18.5 bytes \$\endgroup\$
    – The Thonnu
    Commented May 2, 2023 at 9:15
1
\$\begingroup\$

Wolfram Language (Mathematica), 98 95 bytes

StringRiffle[Switch[#,1,"AM",26,"PM",0,"00",_,ToString@(#-1)]&/@LetterNumber@Characters@#,":"]&

Try it online!

\$\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.