Pigpen Cipher Encryption

10

1

Pigpen Cipher Encryption

Your mission is simple: to write a program which receives text as input and outputs an ASCII representation of it in the Pigpen Cipher.

Input

ASCII-only (no Unicode) characters. You must be able to handle at least 16384 characters and 256 lines.

Output

  • Replace all characters which are not new lines or in ABCDEFGHIJKLMNOPQRSTUVWXYZ or abcdefghijklmnopqrstuvwxyz with spaces.
  • Case-insensitively, replace each letter with its encrypted form (see next section), inserting a trailing space on each of the three lines after each. Each encoded character is a 3*3 block of ASCII art. Replace spaces with 3*3 blocks of spaces.
  • All the characters should be on the same three lines (call these three lines one pigpen-line), unless there is a new line, which starts a new pigpen-line. Leave a normal line blank between pigpen-lines.

The Cipher

  |       | |       |
 .|       |.|       |.
--+ for J +-+ for K +-- for L

--+       +-+       +--
 .|       |.|       |.
--+ for M +-+ for N +-- for O

--+       +-+       +--
 .|       |.|       |.
  | for P | | for Q |   for R

(ABCDEFGHI are the same as JKLMNOPQR, but with the . replaced by a space)

\./
 V  for W (note the row of 3 spaces on the top)

 ^
/.\ for Z (note the 3 spaces on the bottom)


 \
 .>
 /  for X (note the leading spaces)

 /
<.
 \  for Y (note extra trailing spaces)

(STUV are like WXYZ, but with the . replaced by a space)

Example

The input "hEllo,wORLd" should produce:

+-+ +-+ |   |   +--         +-- +-- |   --+
| | | | |.  |.  |.      \./ |.  |.  |.    |
| | +-+ +-- +-- +--      V  +-- |   +-- --+

The base64 encoding of the above, with a trailing new line, is below. The md5sum is 6f8ff1fed0cca4dd0492f9728ea02e7b.

Ky0rICstKyB8ICAgfCAgICstLSAgICAgICAgICstLSArLS0gfCAgIC0tKwp8IHwgfCB8IHwuICB8
LiAgfC4gICAgICBcLi8gfC4gIHwuICB8LiAgICB8CnwgfCArLSsgKy0tICstLSArLS0gICAgICBW
ICArLS0gfCAgICstLSAtLSsK

Without a trailing new line, the md5sum is 581005bef7ee76e24c019d076d5b375f and the base64 is:

Ky0rICstKyB8ICAgfCAgICstLSAgICAgICAgICstLSArLS0gfCAgIC0tKwp8IHwgfCB8IHwuICB8

LiAgfC4gICAgICBcLi8gfC4gIHwuICB8LiAgICB8CnwgfCArLSsgKy0tICstLSArLS0gICAgICBW ICArLS0gfCAgICstLSAtLSs=

Rules

  • Standard loopholes are forbidden.
  • This is code golf. Shortest code wins.
  • In languages which cannot accept multiple lines of input at a time (e.g. JavaScript with prompt()), use * (or some other character) as a line separator.

Erranda

  • The example was missing a few spaces (A space should consist of the trailing spaces of the previous character, if any, itself, and its own trailing spaces). This has now been fixed.

user16402

Posted 2014-09-11T19:28:40.867

Reputation:

1I remember playing with this as a kid, but never knew the name of it. Thanks! – Geobits – 2014-09-11T19:30:39.527

Can I use a custom font? :-) – Florian F – 2014-09-11T19:47:57.073

@FlorianF No... – None – 2014-09-11T19:52:49.527

Coding in javascript. Usually prompt is used for input, but it accepts a single line only. Could I use a special char (like '*') to mark a new line in input?. – edc65 – 2014-09-13T18:04:35.483

@edc65 Yes, you may – None – 2014-09-13T18:11:09.053

As pointed out by Claudiu, there are 4 spaces between Hello and World in your example. If I render a space as 3x3 chars block and add 1 space before and 1 space after, I get 5 spaces between words. Am I wrong? – edc65 – 2014-09-15T07:51:40.543

@edc65 no you aren't, thanks – None – 2014-09-15T10:37:38.300

@edc65 please edit it in – None – 2014-09-15T10:38:03.170

Next up: Run all the answers through themselves, whichever has the least spaces in it wins. – cjfaure – 2014-09-15T12:05:12.167

@professorfish: could you add md5s for the output if there are 5 spaces between words? I had that at first and had to add a few chars to handle 4 spaces. – Claudiu – 2014-09-15T14:59:33.277

@Claudiu I've fixed it – None – 2014-09-15T19:29:57.640

Answers

4

JavaScript (ES6) 312 327 340 372 446

Not counting indentation white space and newlines - could be golfed more. Using an '*' to mark new lines in input, as prompt accepts a single line.

console.log(prompt().split('*').map(s=>
  [0,1,2].map(r=>
  [...s].map(c=>o+=n+
    '   \\1/ \\ /1\\ /  V  ^  1><1 --++-++-- 1||1||1 '.substr(
    (c=(32|c.charCodeAt())-97)<0|c>25?0:c<18
     ?27+3*'330441552030141252033144255'[f=8,c%9*3+r]
     :3*'482630015274'[f=21,c%4*3+r],3,n=' ')
  .replace(1,' .'[r&c>f])
  ,n='\n'),o=''
)&&o).join('\n'))

Test in FireFox/FireBug console

Input: ABCDEFGHI*JKLMNOPQR*STUV*WXYZ*HeLlO WoRlD!

  | | | |   --+ +-+ +-- --+ +-+ +--
  | | | |     | | | |     | | | |  
--+ +-+ +-- --+ +-+ +--   | | | |  

  | | | |   --+ +-+ +-- --+ +-+ +--
 .| |.| |.   .| |.| |.   .| |.| |. 
--+ +-+ +-- --+ +-+ +--   | | | |  

     \   /   ^ 
\ /   > <   / \
 V   /   \     

     \   /   ^ 
\./  .> <.  /.\
 V   /   \     

+-+ +-+ |   |   +--         +-- +-- |   --+    
| | | | |.  |.  |.      \./ |.  |.  |.    |    
| | +-+ +-- +-- +--      V  +-- |   +-- --+      

edc65

Posted 2014-09-11T19:28:40.867

Reputation: 31 086

You have 5 spaces between the o and w in "Hello world", the OP only has 4 – Claudiu – 2014-09-14T23:15:24.783

@Claudiu each character (even blank, char 32) 3 spaces, separator between chars 1 space. 1+3+1 == 5. I'll check with OP – edc65 – 2014-09-15T07:45:26.487

Yea it definitely makes more sense with 5. I thought he specifically wanted 4 as a special-case, but good thing you asked! – Claudiu – 2014-09-15T15:36:06.440

3

C# - 921 720

Obviously not a winning entry, but this looked like too much fun to pass off :)

Program takes input as a single, then prints the pigpen. To input multiple lines, use an underscore (_) as seen in output.

Code

using System;class P{static void Main(){
int i,y,j,k,w,z;string[]g=Console.ReadLine().ToLower().Split('_');
var d="_________  |b .|b--+_| |b|.|b+-+_|  b|. b+--_--+b .|b--+_+-+b|.|b+-+_+--b|. b+--_--+b .|b  |_+-+b|.|b| |_+--b|. b|  _____   b\\./b v _ \\ b .>b / _ / b<. b \\ _ ^ b/.\\b   _  b  b  ".Replace('b','\n').Split('_');
for(i=0;i<d.Length;i++){if(d[i]==""){d[i]=i<17?d[i+9]:d[i+4];d[i]=d[i].Replace('.',' ');}}
for(y=0;y<g.Length;y++){string o="",s,e=g[y];var r=new string[z=e.Length][];
for(i=0;i<z;i++){if(e[i]-97<0|e[i]-97>25)e=e.Replace(e[i],'{');
o+=d[e[i]-97]+'_';r[i]=(o.Split('_')[i].Split('\n'));}
for(j=0;j<3;j++)for(k=0;k<(w=r.Length);k++){
s=r[k][j];Console.Write(k==w-1?s+'\n':s+' ');}}
Console.ReadLine();}}

Concept

The cipher uses a some character sequences that get duplicated quite a bit. For example, '--' shows up 16 times and '__' (two spaces) shows up 20 times. I replace these sequences with single-character symbols and switch them out at runtime, cutting the number of characters needed to store the pigpen cipher in half. Similarly, a newline usually requires two characters, but is replaced by a symbol (n) and switched out later.

The program handles multiple lines of input by splitting the input into an array where each element is a single line of input. The program then simply runs the cipher on each line separately.

This is my first golf in any language, so there is probably a lot that can be done to improve this code.

Output

hEllo,wORLd
+-+ +-+ |   |   +--        +-- +-- |   --+
| | | | |.  |.  |.     \./ |.  |.  |.    |
| | +-+ +-- +-- +--     v  +-- |   +-- --+

code_golf
|   +-- --+ +-+
|   |.    | | |
+-- +-- --+ +-+
--+ +-- |   +--
  | |.  |.  |
  | +-- +-- +--

multi_line_input
--+  /  |    \  +--
 .| <   |.    > |
--+  \  +--  /  |
|   +-- +-+ +-+
|.  |   |.| | |
+-- |   +-+ +-+
+-- +-+ --+  /   \
|   |.|  .| <     >
|   +-+   |  \   /

jrbuchner

Posted 2014-09-11T19:28:40.867

Reputation: 31

1I don't know C#, but there appears to be an unnecessary space in for(int i=0;i<p.Length; i++) (near the middle) – None – 2014-09-13T11:42:30.897

Thanks professorfish, there was another one I missed as well – jrbuchner – 2014-09-13T12:02:32.750

1In m♥lti \n lin♣e \n input, my phone renders that as having a heart instead of u in multi, and a club between the n and the e in line. Why is that? – Beta Decay – 2014-09-14T07:00:21.830

2@BetaDecay I think it is intended, to show the handling of low ASCII chars – edc65 – 2014-09-14T07:24:36.490

The heart and club were put there to demonstrate compliance with the challenges' rule : Replace all characters which are not new lines or in ABCDEFGHIJKLMNOPQRSTUVWXYZ or abcdefghijklmnopqrstuvwxyz with spaces – jrbuchner – 2014-09-14T07:45:40.873

You have 5 spaces between the o and w in "Hello world", the OP only has 4 – Claudiu – 2014-09-14T23:16:11.580

Thanks for pointing that out Claudiu, it's fixed it now. – jrbuchner – 2014-09-15T02:15:29.840

Maybe you fixed it too early, see new comments above – edc65 – 2014-09-15T11:56:22.507

2

Python 2, 180 + 78 + 1 + 3 = 262 characters

The 180-byte program (last two newlines are tabs):

L=open('f','rb').read().decode('zip')
while 1:
 n=raw_input()
 for s in(0,3,6):
    for c in n:w=ord(c.lower())-97;print''.join(L[w+(s+i)*26]for i in(0,1,2))if-1<w<27 else'  ',
    print

Requires a 78-byte file called 'f' to be same directory (+1 byte for filename), which contains the following:

$ hexdump f
0000000 9c78 a853 d1a9 d6d5 2206 3805 0103 c174
0000010 c100 8b88 07d1 9ae1 051a 4ab0 385d ae03
0000020 2803 8a82 3a80 406c ae18 0f42 6006 0c1c
0000030 0a2d 31fa 6076 ee8c a030 0e14 2987 8428
0000040 7501 3080 c39a 5a10 0014 21c7 7333
000004e

The base64 encoding of file f is:

eJxTqKnR1dYGIgU4AwF0wQDBiIvRB+GaGgWwSl04A64DKIKKgDpsQBiuQg8GYBwMLQr6MXZgjO4w
oBQOhykohAF1gDCawxBaFADHITNz

The program exits with an exception, 2>_ suppresses the error (+3 bytes):

$ echo "hEllo,wORLd" | python pigpen.py 2>_| ./md5.py
7ed49b7013a30cc3e84aa807f6585325

Explanation:

I created a look-up table, L, which is a mapping of {position_in_3x3_block: {letter_being_encrypted: symbol_for_letter_at_position}}, stored in a flat array. The program prints the letters by doing a simple look-up for each position.

Claudiu

Posted 2014-09-11T19:28:40.867

Reputation: 3 870

You should add one byte for f and three bytes for 2>_ – None – 2014-09-15T07:23:48.470

0

Perl 5 -lF, 297 288 261 231 bytes

$,=$";$_=' .||.||. ';chomp@F;map{@r=/.../g;say map{/[a-z]/i?$r[-65+ord uc]:$"x3}@F}(y/./ /r.y/.| /-+-/r x2)x2 .'    \\  /  ^ 'x2,y/./ /r x3 .$_ x3 .'\\ /  ><  / \\\\./ .><. /.\\',(y/.| /-+-/r x2 .y/./ /r)x2 .' V  /  \\    'x2;say''

Try it online!

There's probably still a bit here that could be golfed further.

Xcali

Posted 2014-09-11T19:28:40.867

Reputation: 7 671