8
\$\begingroup\$

Given a string to encode, and a number of columns (the key), encode the string as follows:

I will be using the example Hello, world! and the key 3

First, write out the number of columns:

1 2 3

Next, write the text starting from the upper left, one character per column, and when you run out of columns, go to the next line.

1 2 3
H e l
l o ,
  w o
r l d
!

Now, to get your encoded text, read the text starting from the top left corner, but this time, first read one column, and then the next, and so on. If there is not a character in the slot, put a space.

Hl r!eowl l,od 

Note that here, there is a trailing space.

This is your encoded text.

Another test case is Programming Puzzles and Code Golf SE with key 5:

1 2 3 4 5
P r o g r
a m m i n
g   P u z
z l e s  
a n d   C
o d e   G
o l f   S
E

The encoded text is PagzaooErm lndl omPedef gius rnz CGS.

More test cases

"abcdefghijklmnopqrstuvwxyz", 2 -> "acegikmoqsuwybdfhjlnprtvxz"
"codegolf.stackexchange.com", 4 -> "cg.ccgoooskhemdltea. efaxnc "
"Pen Pineapple Apple Pen!!!", 7 -> "PeAeeapnnpp! pl!Ple!ie  n P "
"1,1,2,3,5,8,13,21,34,55,89", 10 -> "18,,,5115,3,2,8,2931 ,, 53 ,4 "

Remember, this is , so the code with the fewest bytes wins.

\$\endgroup\$
  • \$\begingroup\$ Oops, nope, my fault \$\endgroup\$ – Oliver Ni Oct 28 '16 at 20:11
  • \$\begingroup\$ Related. \$\endgroup\$ – AdmBorkBork Oct 28 '16 at 20:11
  • \$\begingroup\$ @TimmyD Fixed.. \$\endgroup\$ – Oliver Ni Oct 28 '16 at 20:12
  • 5
    \$\begingroup\$ I think you should include a few more test cases to verify that padding is handled correctly. \$\endgroup\$ – Dennis Oct 28 '16 at 22:24
  • \$\begingroup\$ Your new test case follows exactly the same pattern as the old one. A potential edge case occurs when the string's length is a multiple of the key, e.g., Programming Puzzles and Code Golf, 3. \$\endgroup\$ – Dennis Oct 29 '16 at 2:06

25 Answers 25

5
\$\begingroup\$

MATL, 4 bytes

e!1e

Try it online!

This is about as straightforward as possible. e is a builtin that reshapes a matrix into n rows. So we read in input1 as a string, and shape into a matrix with input2 rows:

Hl r!
eowl 
l,od 

Then, we transpose it to get this:

Hel
lo,
 wo
rld
!  

After that, we just call 1e to reshape it into a single row, and display it as a string.

As you can see in this sample program, the "reshape" function conveniently adds as many zeroes as necessary for the matrix to be a perfect rectangle. When displaying as a string, MATL treats '0's as spaces, so this automatically fills in the necessary number of spaces for no extra work.

\$\endgroup\$
  • \$\begingroup\$ and the code is almost palindromic! :-) \$\endgroup\$ – Luis Mendo Oct 28 '16 at 20:49
  • 1
    \$\begingroup\$ @LuisMendo Oh, It's definitely a palindrome, it's just that my shift key is broken. :P \$\endgroup\$ – DJMcMayhem Oct 28 '16 at 20:50
5
\$\begingroup\$

Jelly, 3 bytes

sz⁶

TryItOnline!

How?

sz⁶ - Main link: string, columns
s   - split string (a list of characters) into chunks of length column
 z  - transpose the resulting list of lists with filler
  ⁶ - literal ' '
    - implicit print
\$\endgroup\$
  • \$\begingroup\$ This doesn't include the filler spaces. \$\endgroup\$ – xnor Oct 28 '16 at 20:29
  • \$\begingroup\$ I just didn't include the trailing space when I typed the argument for the example. \$\endgroup\$ – Jonathan Allan Oct 28 '16 at 20:33
  • \$\begingroup\$ The input doesn't have a trailing space. You're required to insert extra spaces as padding when the string length isn't a multiple of the number. \$\endgroup\$ – xnor Oct 28 '16 at 20:35
  • \$\begingroup\$ Is it correct now? \$\endgroup\$ – Jonathan Allan Oct 28 '16 at 20:41
  • 1
    \$\begingroup\$ Yup, looks good. \$\endgroup\$ – xnor Oct 28 '16 at 20:42
2
\$\begingroup\$

PHP, 85 Bytes

for(;$i<$x=$argv[2];$i++)for($j=0;$j<strlen($t=$argv[1])/$x;)echo$t[$i+$j++*$x]??" ";

PHP, 90 Bytes

for(;$i<$x=$argv[2];$i++)foreach(array_chunk(str_split($argv[1]),$x)as$a)echo$a[+$i]??" ";
\$\endgroup\$
2
\$\begingroup\$

Ruby, 78 67 65 bytes

->s,k{s.gsub!(/(.)(.{,#{k-=1}})/){$><<$1
$2.ljust k}while s=~/./}

See it on eval.in: https://eval.in/668412

Ungolfed

->s,k{
  s.gsub!(/(.)(.{,#{ k -= 1 }})/) {
    $> << $1
    $2.ljust k
  } while s =~ /./
}
\$\endgroup\$
2
\$\begingroup\$

Pyth - 5 bytes

s.tcF

Try it online here.

\$\endgroup\$
  • \$\begingroup\$ +1 Much better than my ugly solution. :) \$\endgroup\$ – boboquack Oct 29 '16 at 2:02
  • \$\begingroup\$ @boboquack don't worry, pyth has its own "idiomatic style" that's actually quite a bit different from python, and you'll learn it as you write more programs (and start to remember the command list :P). Good luck! \$\endgroup\$ – Maltysen Oct 29 '16 at 5:30
2
\$\begingroup\$

Python 2, 46 bytes

lambda s,n:(s[0]+(s[1:]+-len(s)%n*' ')*n)[::n]

The idea is to take the input string, copy it n times with the first character from removed, then takes every n'th character.

Let's look for example at s="abcdef", n=3, where the length is a multiple of n:

abcdefbcdefbcdef
^  ^  ^  ^  ^  ^
a  d  b  e  c  f

The first cycle through the string takes every nth character from the first one. Then, each subsequent cycle shifts one index to the right because the first character is skipped. To ensure that the length is a multiple of n, the initial string is padded with spaces.

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

Japt, 15 bytes

U+SpV f'.pV)y q

Test it online!

Japt has an "all subsections of length N" built-in, but neither a "all non-overlapping subsections" nor "every Nth char". Suddenly, there is a gaping hole in my life...

Explanation

U+SpV            // Take U concatenated with V spaces.
      f'.pV)     // Take every substring of 3 chars.
            y    // Transpose the resulting array.
              q  // Join on the empty string.
                 // Implicit: output last expression
\$\endgroup\$
1
\$\begingroup\$

Python 2, 58 bytes

lambda s,n:`sum(zip(*zip(*n*[iter(s+' '*~-n)])),())`[2::5]

Test it on Ideone.

\$\endgroup\$
  • 1
    \$\begingroup\$ I really like def f(s,n):t=[*s,' '];del t[print(end=s[::n]):f(''.join(t),n-1):n], but it's too long... \$\endgroup\$ – Dennis Oct 29 '16 at 0:28
1
\$\begingroup\$

JavaScript (ES6), 84 bytes

It's a recursive solution.

f=(s,k,i=0,r=Math.ceil(s.length/k),c=s[i%r*k+i/r|0])=>k*r==i?'':(c?c:' ')+f(s,k,++i)
\$\endgroup\$
1
\$\begingroup\$

R, 92 81 bytes

function(x,n)cat(t(matrix(c(el(strsplit(x,"")),rep(" ",-nchar(x)%%n)),n)),sep="")

Try it on R-fiddle

This turned out to be a bit of a headache because R automatically recycles the input vector when the rows or column specified in the matrix creation is not a multiple of the length of the input. Therefore we have to pad the vector with -nchar(x)%%n spaces before passing it to the matrix function.

The last step is just transposing the matrix and printing it.

\$\endgroup\$
  • \$\begingroup\$ What's the purpose of l=nchar(x)? You don't seem to be using l anywhere. Function el is quite the discovery though, +1. \$\endgroup\$ – plannapus Oct 30 '16 at 20:31
  • \$\begingroup\$ @plannapus I honestly don't know why I put it there. I believe it is a remnant of how I first calculated the number of times the blank space was being repeated. Good catch though. \$\endgroup\$ – Billywob Oct 30 '16 at 20:38
1
\$\begingroup\$

Perl, 61 bytes

54 bytes of codes and -F -pi flags.

for$l(1..$^I){$\.=$F[$^I*$_+~-$l]//$"for 0..$#F/$^I}}{

Takes the input string without final newline, and the key should be placed after -i flag :

$ echo -n "Hello, World!" | perl -F -pi3 -E 'for$l(1..$^I){$\.=$F[$^I*$_+~-$l]//$"for 0..$#F/$^I}}{'
Hl r!eoWl l,od 
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 43 40 bytes

Thanks to miles for saving three bytes!

Join@@Thread@Partition[##,#2,{1,1}," "]&

Unnamed function taking two arguments, an array of characters and an integer; returns an array of characters. Most of the heavy lifting is done by the Thread function, which (in this context) exchanges rows and columns. Partition needs to be called with a couple of useless arguments so that it will pad with the fifth argument " ".

\$\endgroup\$
  • \$\begingroup\$ You can use Thread also instead of Transpose Join@@Thread@Partition[##,#2,1," "]& \$\endgroup\$ – miles Nov 1 '16 at 14:05
  • \$\begingroup\$ whoa. I get it now! \$\endgroup\$ – Greg Martin Nov 1 '16 at 16:15
0
\$\begingroup\$

Ruby, 89 bytes

->s,i{t="";i.times{|n|s.ljust(i*(s.size*1.0/i).ceil).scan(/#{?.*i}/).each{|j|t<<j[n]}};t}

Terrible score, tips appreciated.

\$\endgroup\$
  • \$\begingroup\$ Use size instead of length for one byte. \$\endgroup\$ – Jordan Oct 28 '16 at 20:37
  • \$\begingroup\$ @Jordan Wouldn't it be two? \$\endgroup\$ – dkudriavtsev Oct 28 '16 at 20:41
0
\$\begingroup\$

Perl, 87 bytes

($a,$b)=@ARGV;for$c(1..$a){for(0..(length$a)/$b){$e.=substr($a,$b*$_+$f,1)}$f++;}say$e;

Accepts two arguments as parameters and Usage:

perl -M5.010 encol.pl "Hello, World!" 3
Hl r!eoWll,od
\$\endgroup\$
  • \$\begingroup\$ @Dada Why don't you post it as your own answer? \$\endgroup\$ – boboquack Oct 28 '16 at 23:43
0
\$\begingroup\$

Pyth, 40 bytes

=Zw=+Z*d+Q-*Q/lZQlZV*QlZIq%%NlZQ/NlZp@ZN

Test it here

Probably the ugliest Pyth code ever, but this is my first attempt at Pyth.

=Zw=+Z*d+Q-*Q/lZQlZV*QlZIq%%NlZQ/NlZp@ZN
         Q                               Set Q to eval(input())
=Zw                                      Initialises Z to next input string
              lZ                         Gets the length of Z
             /lZQ                        Integer divides lZ by Q
           *Q/lZQ                        Multiplies that result by Q
          -*Q/lZQlZ                      Subtracts the length of Z from that
        +Q-*Q/lZQlZ                      Adds Q to that
                                         (This is how many spaces to pad)
      *d+Q-*Q/lZQlZ                      Gets that many spaces (d is set to ' ')
   =+Z*d+Q-*Q/lZQlZ                      Appends that to Z
                    *QlZ                 Multiplies Q by lZ
                   V*QlZ                 Does a for loop for integers in that range, on N
                           %NlZ          Gets N modulo lZ
                          %%NlZQ         Gets that modulo Q
                                         This is the column of the letter at index N mod Q
                                /NlZ     Gets the column that is being printed
                        Iq%%NlZQ/NlZ     If they are equal...
                                    p@ZN Print the index of N into Z without a newline
                                         (This is implicitly modulo the length of Z)

If anyone has tips to improve my golfing, please leave a comment!

\$\endgroup\$
  • \$\begingroup\$ Don't worry, my first try with Pyth was just as long :) The number of spaces to pad is equal to (-len(Z))%Q, so you can replace +Q-*Q/lZQlZ with %_lZQ. (Alternatively, you could rearrange +Q-*Q/lZQlZ to +-*/lZQQlZQ. It's not shorter, but +-*/ looks cool ;) ) \$\endgroup\$ – ETHproductions Oct 29 '16 at 2:24
0
\$\begingroup\$

Actually, 12 bytes

Golfing suggestions welcome, especially if you can figure out a golfier way to pad spaces. Try it online!

;' *(q╪dX┬ΣΣ

Ungolfing

      Implicit input s, then n.
;     Duplicate n. Stack: n, n, s
' *   Push n spaces.
(q    Rotate s to TOS and append the spaces to the end of s.
╪     Split s into n-length substrings.
dX    Dequeue and discard any extra spaces that remain after chunking.
      This works even when we didn't need to add spaces in the first place.
┬     Transpose the remaining substrings. This returns a list of lists of chars.
Σ     Sum the transposed substrings into one list of chars.
Σ     Sum the list of chars into one string.
      Implicit return.

Another 12-byte version

In this version, the order of the inputs is reversed, but this can be changed if that isn't allowed. Golfing suggestions welcome. Try it online!

│l±%' *o╪┬ΣΣ

Ungolfing

      Implicit input n first, then s.
│     Duplicate stack. Stack: s, n, s, n
l±    Push -len(s).
%     Push -len(s)%n, which gets the number of spaces we need to pad with. Call this m.
' *   Push m spaces to the stack.
o     Append the spaces to the end of s.
╪     Split s into n-length substrings.
┬     Transpose these substrings. This returns a list of lists of chars.
Σ     Sum the transposed substrings into one list of chars.
Σ     Sum the list of chars into one string.
      Implicit return.
\$\endgroup\$
0
\$\begingroup\$

Pyke, 10 bytes

k=.,Rc.,ss

Try it here!

\$\endgroup\$
0
\$\begingroup\$

C#, 161 bytes

I am so sorry.

(s,i)=>String.Join("",Enumerable.Range(0,i).SelectMany(x=>Enumerable.Range(0,s.Length/i+1).Select(n=>(n*3+x)).Where(m=>m<s.Length).Select(o=>s.Substring(o,1))));
\$\endgroup\$
0
\$\begingroup\$

GolfSharp,(non competing) 82 bytes

(s,i)=>r(0,i).m(x=>r(0,s.L()/i+1).s(n=>(n*3+x)).w(m=>m<s.L()).s(o=>s.R(o,1))).j();
\$\endgroup\$
0
\$\begingroup\$

Groovy, 90 Bytes

{s,n->(s.padRight((int)(s.size()/n+1)*n) as List).collate(n).transpose().flatten().join()}

Pad the input by the ceiling of the size divided into n chunks.

Get the padded string as a list of characters.

Collate into n chunks and transpose.

({s,n->(s.padRight((int)(s.size()/n+1)*n) as List).collate(n).transpose().flatten().join()})("Programming Puzzles and Code Golf SE",5)

Results in:

PagzaooErm lndl omPedef gius    rnz CGS
\$\endgroup\$
0
\$\begingroup\$

Python 3, 48 bytes

lambda c,k:''.join([c[i:-1:k]for i in range(k)])
\$\endgroup\$
0
\$\begingroup\$

Powershell, 57 bytes

param($s,$n)$r=,''*$n
$s|% t*y|%{$r[$i++%$n]+=$_}
-join$r

Test script:

$f = {

param($s,$n)$r=,''*$n
$s|% t*y|%{$r[$i++%$n]+=$_}
-join$r

}

@(
    ,("abcdefghijklmnopqrstuvwxyz", 2  , "acegikmoqsuwybdfhjlnprtvxz")
    ,("codegolf.stackexchange.com", 4  , "cg.ccgoooskhemdltea.efaxnc")
    ,("Pen Pineapple Apple Pen!!!", 7  , "PeAeeapnnpp! pl!Ple!ie n P")
    ,("1,1,2,3,5,8,13,21,34,55,89", 10 , "18,,,5115,3,2,8,2931,,53,4")
) | % {
    $s,$n,$expected = $_
    $result = &$f $s $n
    "$($result-eq$expected): $result"
}

Output:

True: acegikmoqsuwybdfhjlnprtvxz
True: cg.ccgoooskhemdltea.efaxnc
True: PeAeeapnnpp! pl!Ple!ie n P
True: 18,,,5115,3,2,8,2931,,53,4
\$\endgroup\$
0
\$\begingroup\$

SINCLAIR ZX81/TIMEX TS-1000/1500 BASIC, 134 tokenized BASIC bytes

 1 INPUT A$
 2 INPUT A
 3 LET C=-SGN PI
 4 FOR I=SGN PI TO A
 5 PRINT I;
 6 NEXT I
 7 PRINT
 8 FOR I=SGN PI TO LEN A$
 9 LET C=C+SGN PI
10 IF C=A THEN LET C=NOT PI
11 IF NOT C AND I>SGN PI THEN PRINT
12 PRINT A$(I);
13 NEXT I

The first parameter A$ is the string value that you want to cipher, and the second A is the number of columns that you want to cipher to. The variable C is used to add in a new line after A characters.

Lines 4 to 6 inclusive print out the column numbers at the top of the screen area.

Line 7 adds a new line ("\r\n" equivalent).

Lines 8 - 13 will then print out each character of A$.

This programme does not require a RAM expansion to work.

ZX81 column cipher using advanced Sinclair BASIC

\$\endgroup\$
0
\$\begingroup\$

K (oK), 27 bytes

Solution:

{,/+(0N;y)#(y*-_-(#x)%y)$x}

Try it online!

Explanation:

{,/+(0N;y)#(y*-_-(#x)%y)$x} / the solution
{                         } / lambda taking implicit x and y
                        $x  / pad x 
           (           )    / do this together
                     %y     / divide by y
                 (  )       / do this together
                  #x        / count (#) length of x
                -           / negate \
               _            / floor   | ceiling
              -             / negate /
            y*              / multiply by y
          #                 / reshape
    (0N;y)                  / null by y grid
   +                        / transpose
 ,/                         / flatten
\$\endgroup\$
0
\$\begingroup\$

05AB1E (legacy), 3 bytes

ôζJ

The Python legacy version is used instead of the Elixir rewrite, because the new version doesn't implicitly convert strings to characters when using zip, which the old version did.

Try it online or verify all test cases.

Explanation:

ô      # Split the (implicit) input-String into chunks of size (implicit) input-integer
       #  i.e. "Hello, world!" and 3 → ['Hel','lo,',' wo','rld','!']
 ζ     # Zip, swapping rows and columns (with space filler by default)
       #  i.e. ['Hel','lo,',' wo','rld','!'] → ['Hl r!','eowl ','l,od ']
  J    # Join the list of strings together (and output implicitly)
       #  i.e. ['Hl r!','eowl ','l,od '] → 'Hl r!eowl l,od '
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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