Substitution cipher

-7

0

A substitution cipher is an encoding method where each letter in the alphabet is replaced with a fixed, different one; for example, given the following substitution map:

abcdefghijklmnopqrstuvwxyz
            ||
qwertyuiopasdfghjklzxcvbnm

The phrase "we all love cryptography" would be encoded as "vt qss sgct eknhzgukqhin".

The program will continuously read its input, one line at time; the first line will contain the substitution map, in the form of all 26 letters, in any order, without repetitions, missing letters or extraneous characters; it will be interpreted as "the first letter is the substitution for A, the second letter is the substitution for B [...] the 26th letter is the substitution for Z"; no output will be provided after reading it. For each subsequent line, the program will output the encoded text corresponding to the line. Only letters will be encoded; numbers, symbols and whitespaces will be simply copied to the output.

For simplicity, all input (including the substitution map) will only contain lowercase characters.

Sample input:

qwertyuiopasdfghjklzxcvbnm
hello
bye!
i don't know.

Sample output:

itssg
wnt!
o rgf'z afgv.

As usual, the shortest solution wins.


Additional clarifications on input:

  • The program must read its input stream (I thought that was clear); command line parameters, files, named pipes, network sockets, quantum entanglement or extra sensorial perceptions are not allowed.
  • The input must include only the actual text to be processed; quotes, brackets, commas or any other symbol, if found, should simply be copied to the output as they are.
  • No additional characters should be required in the input. If your program requires the input text to be placed in quotes, brackets, commas or any other delimiter, then You Are Doing It Wrong (TM).
  • "Line" is defined as a string of characters followed by a newline; the actual implementation of "newline" if usually left to the OS, but if you need to go into its details, just use whatever you prefer.
  • An empty line is no special case; the program could either print an empty line or do nothing, but it should not print any actual text, crash, exit, destroy the operating system, set fire to the house, collapse the Sun in a black hole, summon demons from other planes of existence or replace your toothpaste with mayonnaise.
  • There is no requirement for the program to run interactively; it's free to suck all its input in and then print all its output; there is also not any time limit on its execution, although it would be definitely preferable for it to terminate before the heat death of the universe.

Massimo

Posted 2016-04-15T22:56:52.023

Reputation: 145

Question was closed 2016-11-02T16:56:00.757

Exiting with crash (after producing the correct output) is allowed by default. Does your edit "should not crash" rule that out? Because in that case you may be breaking some already posted answers. Also, I suggest you remove the black-hole and toothpaste stuff, as it adds nothing to the challenge – Luis Mendo – 2016-04-16T00:54:00.503

1@LuisMendo If the program exits with a crash after the input is exhausted and the correct output is procuced, then yes, it's ok. – Massimo – 2016-04-16T00:56:19.220

I thought the input format was specified very clearly; I didn't know it's considered usual practice here to rearrange input as needed. However, I saw the question lose several points after some people complained about the rules on the input format, so clearly someone got quite upset on this. Sorry, I didn't mean any harm. – Massimo – 2016-04-16T02:30:32.067

But please, when a question *clearly specifies* the input format for the required program, just don't go assuming you can change it at will... and then complain if your answer is rejected. – Massimo – 2016-04-16T02:31:05.603

11

@Massimo Arbitrarily overriding the defaults by not allowing a function and requiring a cumbersome input format are both considered things to avoid. The rules are ultimately up to you, but don't be surprised to get downvotes if your the community believes your challenge needlessly restricts participation. Note that some languages simply cannot do IO loops.

– xnor – 2016-04-16T04:25:28.723

6@Massimo Furthermore, saying thing like "If your program requires the input text to be placed in quotes, brackets, commas or any other delimiter, then You Are Doing It Wrong (TM)" is needlessly confrontational and contrarian, as the community has discussed and decided to allow such things in general. Again, you can override them, but expect a poor reaction, as there seems to be no good reason. Perhaps you have experience with other golfing sites that do expect exact inputs, but that's not how we work around here. I suggest you stick around a bit and get a sense of the usual rules and culture. – xnor – 2016-04-16T04:28:59.680

You don't have to quit. Making good questions is hard, but you can still answer them. Also, I wonder why nobody's mentioned the sandbox, where you can post questions and get comments. So yeah, pull out your compiler/interpreter/whateverer and get golfing!

– CalculatorFeline – 2016-04-16T20:26:42.280

@CatsAreFluffy I seriously didn't mean any harm, nor I wanted to start discussions or flame wars; I simply posted a challenge question like there are many... starting an argument about I/O formats was exactly not what I was looking for. This is definitely not the experience I was expecting from this site. – Massimo – 2016-04-16T20:39:21.807

7

Hi Massimo, sorry your first experience as a challenge author was so negative. As you've noticed, the community has grown accustomed to certain freedoms regarding I/O, submission format, etc. It's one of the not-so-obvious facets of this site that unfortunately adds another hurdle to writing a challenge. We have a Sandbox for Proposed Challenges where folks can post their challenge ideas and get (usually more constructive) feedback before going live. I certainly hope you'll stick around and continue to write challenges!

– Alex A. – 2016-04-16T21:36:10.237

5

If you have any questions about how the site works, I encourage you to ask on Meta or join us in chat and we'll try to help however we can. Thanks for being a member of the community and again I hope you'll stay.

– Alex A. – 2016-04-16T21:38:43.720

Answers

9

Convex, 4 6 5 bytes

Crossed out 4 is still regular 4 :(

Note: As @Dennis pointed out, the input format I was using was not up to spec. This version should comply with the new rules, though.

lqT@Ë

Try it online

Explanation:

l       Read a line from input
 q      Read the rest of the input
  T     Push lowercase alphabet ("abcdefghijklmnopqrstuvwxyz")
   @    Rotate the top 3 items on the stack.
    er  Transliterate
        Implied output

Thanks to @LuisMendo for pointing out an error in the program

GamrCorps

Posted 2016-04-15T22:56:52.023

Reputation: 7 058

1Nicely done, especially with your own language! Now let's wait for Dennis to beat this with Jelly. – Fund Monica's Lawsuit – 2016-04-16T00:12:25.207

3Struck out 4 is still regular 4 ;( – user48538 – 2016-04-16T17:22:32.567

Added a link to http://codegolf.stackexchange.com/a/73584/48836 :P

– cat – 2016-04-19T01:35:35.277

5

Pyth, 7 bytes

V.zXNGz

Try it online!

How it works:

V.zXNGz
        G = "abcdefghijklmnopqrstuvwxyz"
        z = input()
V.z     for N in all_input():
   XNGz     N.translate(G,z)    <--- automatically printed

Leaky Nun

Posted 2016-04-15T22:56:52.023

Reputation: 45 011

It looks like with the new rules invalidate your submission, unfortunately. Quotes can't be included in the input like yours does. Don't worry, the new rules affected me too :P – GamrCorps – 2016-04-16T02:13:26.220

@GamrCorps Updated. – Leaky Nun – 2016-04-16T02:21:24.313

3

JavaScript ES6, 65 62 49 bytes

Saved 2 bytes thanks to Neil.

(a,i)=>a.replace(/./g,x=>i[x.charCodeAt()-97]||x)

Takes an string of lines a and a dictionary i.

Conor O'Brien

Posted 2016-04-15T22:56:52.023

Reputation: 36 228

Use [...s] instead of s.split\``. – Neil – 2016-04-15T23:34:57.933

@Neil Ah, yes, of course. – Conor O'Brien – 2016-04-15T23:35:14.810

On second thoughts, s.replace(/./g,x=>...) might be shorter still. – Neil – 2016-04-15T23:36:25.917

@Neil That would make it four bytes longer, no? – Conor O'Brien – 2016-04-15T23:37:43.120

@Neil Is that what you meant? – Conor O'Brien – 2016-04-15T23:39:30.240

Well, I meant instead of the split/join, but that works too, if it's an acceptable input format. – Neil – 2016-04-15T23:45:43.200

@Neil It should be, as that's how the examples are given. – Conor O'Brien – 2016-04-15T23:46:22.137

3

CJam, 12 8 bytes

4 bytes saved thanks to Dennis!

l_$q\@er

Try it online!

Explanation

l        e# read a line
_$       e# fancy way to obtain string "abc...z". Thanks to Dennis!
q        e# read the rest of input as a string with newlines
\@       e# swap, rotate
er       e# transliterate. Implicit display

Luis Mendo

Posted 2016-04-15T22:56:52.023

Reputation: 87 464

@Dennis That's very clever! – Luis Mendo – 2016-04-15T23:46:58.170

3

sh + coreutils, 16 bytes

read s;tr a-z $s

15 bytes if input is from a terminal:

tr a-z `sed 1q`

Neil

Posted 2016-04-15T22:56:52.023

Reputation: 95 035

That won't work. sed will close the stream. (At least it does on my machine.) – Dennis – 2016-04-15T23:37:06.793

@Dennis Ugh, it works when you type it in at the terminal... – Neil – 2016-04-15T23:39:29.777

Oh, I hadn't thought about that possibility... – Dennis – 2016-04-15T23:44:44.673

3

05AB1E, 5 bytes

Code:

[A¹‡,

Explanation:

[      # Start an infinite loop.
 A     # Push the lowercase alphabet.
  ¹    # Push the first input (substitution map).
   ‡   # Transliterate. Since the arity of this function is 3 and there are only 2 values
                        on the stack, it implicitly takes a line of input.
    ,  # Pop and print.

So this continually reads a line of input and prints a line of input after. Uses CP-1252 encoding. This is what I got with the console version:

D:\Golfing\05AB1E>C:\Python34\python.exe 05AB1E.py test.abe
qwertyuiopasdfghjklzxcvbnm
hello
itssg
welcome
vtsegdt
greetings, planet!
ukttzoful, hsqftz!

Trying this online might be a bit weird, since 05AB1E is trying to read another line of input, but there is none, so you need to kill it to receive output (doesn't work all the time). It might be a better idea to do this with the console version of 05AB1E. Try it online!.

Adnan

Posted 2016-04-15T22:56:52.023

Reputation: 41 965

2

JavaScript 89

for(i=prompt,x=i(),n='';p=i();n+=p.replace(/./g,m=>x[m.charCodeAt(0)-97])+"\n");
alert(n)

wolfhammer

Posted 2016-04-15T22:56:52.023

Reputation: 1 219

1

Ruby, 35 31 29 bytes

Credit to @QPaysTaxes for the $_ trick, I had assumed that reading more from the STDIN object $< would change that variable, but it doesn't.

gets
$><<$<.read.tr('a-z',$_)

String#tr is basically a cipher substitution function, making things quite simple.

Value Ink

Posted 2016-04-15T22:56:52.023

Reputation: 10 608

Because you only use c once, you can replace it with gets. Also, I'm not sure if it would work, but you could try replacing {|l| with ->l{. – Fund Monica's Lawsuit – 2016-04-16T00:23:06.443

You can't use it with gets because you're looping through an iterable with map and gets gets data from STDIN each time it's called. Bonus points because $< is the STDIN stream, making things potentially even more hectic. As for the arrow notation, it doesn't save bytes, and IIRC a lambda defined that way needs & in front of the procedure to make it work? – Value Ink – 2016-04-16T06:32:30.413

Oops, you're right. I wasn't paying attention to the function. What you can do is save a byte by just calling gets -- not assigning -- then using $_. As for the lambda notation, I'm not sure. I've almost never used it. – Fund Monica's Lawsuit – 2016-04-16T18:28:05.857

Thanks for the tip! I was able to find more tricks to further save bytes as well. – Value Ink – 2016-04-16T20:39:26.090

1

MATL, 14 bytes

jXKx`jHY2KXEDT

The program exits with an error after producing the correct output (allowed by default).

Try it online

Luis Mendo

Posted 2016-04-15T22:56:52.023

Reputation: 87 464

A single newline is not defined as EOI; if it's found in input, the program should simply not print anything and keep looping until input actually ends. – Massimo – 2016-04-16T00:31:45.363

@Massimo Corrected – Luis Mendo – 2016-04-16T00:42:36.610

0

Python 3, 50 bytes

lambda s,k:s.translate(dict(zip(range(97,122),k)))

Or if we really have to implement an infinite loop:

Python 3, 70 bytes

t=dict(zip(range(97,122),input()))
while 1:print(input().translate(t))

orlp

Posted 2016-04-15T22:56:52.023

Reputation: 37 067

I think you have to take a list of strings instead of one string as input. – Conor O'Brien – 2016-04-15T23:33:41.080

0

Pyth, 34 Bytes 31 Bytes 29 Bytes 27 Bytes

Saved 3 5 7 bytes thanks to Kenny Lau

jmsm?&<JCk123>J96@hQ-J97kdt

Try it out!

poi830

Posted 2016-04-15T22:56:52.023

Reputation: 1 265

You can use V instead of Fd (but you'll have to change the variable names afterwards) :) – Leaky Nun – 2016-04-15T23:29:23.160

You can also save 2 bytes by changing ?XpYpZ to p?XYZ. – Leaky Nun – 2016-04-15T23:32:05.860

An array of strings is not the proper input format. – Massimo – 2016-04-16T01:54:44.647

0

Factor, 155 bytes

The logic is actually pretty simple, it's just constraining to the REPL requirement that costs.

[let "abcdefghijklmnopqrstuvwxyz" readln string>array bi@ zip :> T [ t ] [ T readln string>array [ dup T key? [ T at ] [ ] if ] map "" join print ] while ]

Readable single-function version (don't ever write code like this):

:: monolithic-repl ( -- )
    "abcdefghijklmnopqrstuvwxyz" readln string>array bi@ zip 
  :> table
  [ t ] 
  [ table readln string>array
    [ dup table key? 
      [ table at ] [ ] if 
    ] map
    "" join print 
  ] while ;

Readable, Factored version:

:: cipher-print ( cipher-table -- )
  readln string>array
  [ dup cipher-table key? [ cipher-table at ] [ ] if ] map
  "" join print ;

: cipher-get ( -- cipher )
  "abcdefghijklmnopqrstuvwxyz" readln
  string>array bi@ zip ;

:: cipher-repl ( -- )
  cipher-get :> table
  [ t ] [ table cipher-print ] while ;

cat

Posted 2016-04-15T22:56:52.023

Reputation: 4 989

0

C++, 154 Bytes

#include <iostream.h>
#include "string.h"
using namespace std;

void encript_string() {
char en[26],in[1024];
string s=cin.getline();
strcpy(en,s.c_str());
while(1){
 s=cin.get_line();
 strcpy(in,s.c_str());
 int i=0,m=0;
 while(in[i] != 10) {
  m=in[i]-97;
  cout<<en[m];
 }
 cout<<"\n";
}
}

parth patel

Posted 2016-04-15T22:56:52.023

Reputation: 1

1This is a snippet, which is not allowed by our rules. Submissions must be functions or full programs. – Mego – 2016-04-22T07:54:28.187

Why it displays in same line ?? (Removes new line character ?) – parth patel – 2016-04-22T09:31:42.620

This answer isn't valid because you're missing necessary header includes like iostream and string. – Mego – 2016-04-22T19:53:33.460

I seem to be getting errors from this

– MilkyWay90 – 2019-03-23T17:47:27.370