16
\$\begingroup\$

You must write a program that takes an encrypted string and decrypt it according to specific rules and then print it out. Decryption will occur by performing two operations.

Sample Input Argument 1 (the encrypted string)

HGJILKBADCFE

Operation 1:

Swap the first half of the string with the second half, which should leave you with:

BADCFEHGJILK

Operation 2:

Swap every two characters with each other such as swapping character 1 with 2, 3 with 4, etc., which should leave you with the decrypted string:

ABCDEFGHIJKL

Guidelines:

  • Input Argument 1 will contain only uppercase letters

  • Input Argument 1's length will be between 2 and 100 characters

  • Input Argument 1's length will always be an even number

  • Preferably the input will be taken from the command line (like below).

  • Another Test Case MPORQTSVUXWZYBADCFEHGJILKN is the input, Output is ABCDEFGHIJKLMNOPQRSTUVWXYZ

My Attempt

import sys
_,a=sys.argv
b=len(a)//2
s=a[b:]+a[:b]
print(''.join(x+y for x,y in zip(s[1::2],s[::2])))
\$\endgroup\$
5
  • 6
    \$\begingroup\$ Welcome to code golf! Your challenge is well specified, but I'd suggest removing the wording 'and then print it out' to allow users to submit a function. \$\endgroup\$ – Sisyphus Sep 21 '20 at 2:36
  • 5
    \$\begingroup\$ We have a list of allowed I/O methods by default, and as a code golf challenge, most answers will just ignore the "preferably..." part to save as much bytes as possible. (Also note that some languages simply cannot take command line args.) \$\endgroup\$ – Bubbler Sep 21 '20 at 3:50
  • \$\begingroup\$ Yes but languages like python, ruby and more can do that, and people have submitted answers in that, so they can try that also, right? \$\endgroup\$ – Smilecat Sep 21 '20 at 4:18
  • \$\begingroup\$ Of course they could if they feel like it. But accessing command line arguments is verbose in most languages, so they don't have incentives to do so. (Don't think of giving a bonus for that. It's even worse.) \$\endgroup\$ – Bubbler Sep 21 '20 at 4:24
  • 2
    \$\begingroup\$ You might like to add a test case where the input length is still even but not a multiple of 4, such as ABCDEF. A few submissions haven't handled this correctly (including mine, initially). \$\endgroup\$ – Dingus Sep 21 '20 at 8:04

30 Answers 30

5
\$\begingroup\$

J, 15 bytes

[:,_2|.\-:@#|.]

Try it online!

Straightforward implementation of the formula.


Slightly more interesting (not helpful for J golfing, but maybe for another lang) is that the algorithm can be solved with a scan sum:

  1. First take a 1 followed by -1 3, with -1 3 repeated up to the length of the list.
  2. Scan sum that list.
  3. Rotate the numbers half the list length.
  4. Sort the original according those numbers.

See the TIO for a demo in J.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Your 14 byter is wrong, just like Dingus' previous answer. (Operations 1 and 2 cannot be swapped: try 0123456789.) \$\endgroup\$ – Bubbler Sep 21 '20 at 4:04
5
\$\begingroup\$

Ruby -p, 48 47 bytes

$_=$_[l= ~/$//2,l]+$_[0,l];gsub /(.)(.)/,'\2\1'

Try it online!

Operation 1 is handled by splitting $_ (the predefined global variable that contains the input) into two substrings of equal length; ~/$/ gives the length of the input. Then gsub /(.)(.)/,'\2\1' completes Operation 2 by swapping each pair of characters. (With the -p flag, gsub without a receiver implicitly acts on $_.)

\$\endgroup\$
3
  • 1
    \$\begingroup\$ @Sachin To take input from the command line you could do something like this. \$\endgroup\$ – Dingus Sep 21 '20 at 4:46
  • \$\begingroup\$ I tried swapping like, $_=$_.slice!($_.size/2..-1)+$_, but couldn't understand what you're doing here -> l= ~/$//2,l x_x \$\endgroup\$ – vrintle Dec 5 '20 at 7:36
  • 1
    \$\begingroup\$ @vrintle ~/$/ returns the length of $_. ~/$//2 is just half of this length. Instead of a range, slice (and its [] shorthand) can take a starting position and a length as arguments. Here we start at the halfway point (l= ~/$//2) and take the substring of length l (lowercase L), which gives us the second half of $_. \$\endgroup\$ – Dingus Dec 5 '20 at 12:24
5
\$\begingroup\$

05AB1E, 13 12 bytes

D2äRJ2ι`s.ιJ

Try it online!

-1 thanks to a golfing tip by @Kevin I saw on another answer

Explained

D2äRJ2ι`s.ιJ
  • Duplicate the input (D)
  • Split it into 2 chunks ()
  • Reverse the list and join it into a single string (RJ)
  • Uninterleave that string on every second character ()
  • Push all items from the uninterleaved string onto the stack (```)
  • Interleave those items ()
  • And join the resulting list (J)
\$\endgroup\$
2
  • 2
    \$\begingroup\$ 2ôí is an easier approach than the uninterleave and interleave. :) And you don't need the leading D: 2äRJôíJ (8 bytes). Also, by outputting as a list of characters, this can be 7 bytes: 2ôí2äRS instead. \$\endgroup\$ – Kevin Cruijssen Sep 21 '20 at 8:17
  • \$\begingroup\$ Ah, ignore the 7-byter above. Swapping the two operations doesn't always work unfortunately. The 8-byter is still valid though. \$\endgroup\$ – Kevin Cruijssen Sep 21 '20 at 9:59
5
\$\begingroup\$

APL+WIN, 24 22 bytes

-2 bytes thanks to Jo King

Prompts for input of string:

,⌽n⍴⊖(⌽n←⌽2,.5×⍴s)⍴s←⎕

Try it online! Courtesy of Dyalog Classic

\$\endgroup\$
4
  • \$\begingroup\$ @JoKing Thanks Jo but my ancient APL+WIN interpreter does not have the ⍨ operator nor does it support trains \$\endgroup\$ – Graham Sep 21 '20 at 8:41
  • \$\begingroup\$ The expression ,⌽n⍴⊖(⌽n←⌽2,.5×⍴s)⍴s←⎕ is 22 char in length but 43 byte in size. I always wish APL expressions are counted by number of char instead. \$\endgroup\$ – jimfan Oct 4 '20 at 17:01
  • 1
    \$\begingroup\$ @jimfan Not in APL+WIN and Dyalog Classic. The byte count is the same as the character count. For Dyalog Classic see the TIO link above \$\endgroup\$ – Graham Oct 4 '20 at 17:16
  • \$\begingroup\$ Okay thanks for correcting me. Thumbs up for the answer. \$\endgroup\$ – jimfan Oct 4 '20 at 18:26
5
\$\begingroup\$

R, 78 80 79 bytes

Edit: +2 bytes thanks to Dingus for bug-spotting, and -1 byte thanks to pajonk

n=nchar(s<-scan(,''));o=1:n;cat(substring(s,p<-(o+n/2-2+2*o%%2)%%n+1,p),sep='')

Try it online!

Input given through R console (which could be considered the 'command line' for the R workspace).
R can also be invoked from a (non-R) shell, using the Rscript helper front-end, which would allow command-line arguments to directly follow the call, in which case a modified program could be 87 bytes and called using Rscript decrypt.r HGJILKBADCFE.

Calculates positions of decoded letters, and then outputs rearranged string.

Commented:

 n=nchar(                   # n = number of characters in...
         s<-scan(,''));     # s = the input.
 o=1:n;                     # o = sequence from 1 to n
 p=                         # p = positions of decoded characters:
   (o+n/2-1                 #   - reverse the first & second halves of o
                            #     by adding n/2-1
                            #     (will be fixed with final modulo below) 
         +2*o%%2-1)         #   - then add 2 at every odd position
                            #     and subtract 1 from all, so in effect
                            #     adding to odds & subtracting from evens
                   %%n      #   - all modulo n
                      +1    #   - add 1 to get 1-based indices
 cat(                       # output:
   substring(s,p,p),sep='') #   characters of s from positions p to p
\$\endgroup\$
4
  • \$\begingroup\$ One byte shorter: Try it online! \$\endgroup\$ – pajonk Sep 21 '20 at 11:32
  • \$\begingroup\$ @pajonk Yes! Thankyou! \$\endgroup\$ – Dominic van Essen Sep 21 '20 at 11:50
  • \$\begingroup\$ @pajonk - in case you weren't aware, R is the language of the month this month (Sept 2020)! As you obviously know R, how about giving a shot at a couple of R-golfs...? \$\endgroup\$ – Dominic van Essen Sep 23 '20 at 8:42
  • \$\begingroup\$ Yes, I know. I'm just so infrequent visitor, that all solvable (for me) challenges already have great answers in R. However, I upvote them all! :) \$\endgroup\$ – pajonk Sep 23 '20 at 9:21
3
\$\begingroup\$

Jelly, 7 bytes

ŒHṚFs2U

Try it online!

Equivalently 7 bytes, ṙLH$s2U.

Explanation

ŒHṚFs2U  Main Link
ŒH       Split into two halves of similar length
  Ṛ      Reverse the order (swap the two halves)
   F     Flatten back into a single string
    s2   Slice into chunks of length 2
      U  Reverse each chunk
         Output is implicitly as one string

The other one otates it by $(Half of the string's Length) and then does the same thing for the second part of the challenge.

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

Python 3, 75 bytes

Exactly as asked: input from command line, output to STDOUT.

import sys
_,s=sys.argv
i=1
while s[i:]:print(end=s[i-len(s)//2]);i+=3|i%-2

Try it online!


Python 2, 52 bytes

If we can use a function:

f=lambda s,i=1:s[i:]and s[i-len(s)/2]+f(s,i+3-i%2*4)

Try it online!


The idea of all of these is that the index of the \$i\$'th output character in a string of length \$n\$ is:

$$ i - \frac{n}{2} + (-1)^i $$

Subject to the usual Python indexing semantics. If we rewrite this in an iterative fashion, then the \$i\$'th output character is:

$$ a_i - \frac{n}{2} \text{ where } a_0 = 1 \text{ and } a_i = a_{i-1} + 3 - 4(i\%2) $$

Shorter with certain precedence is:

$$ a_i - \frac{n}{2} \text{ where } a_0 = 1 \text{ and } a_i = a_{i-1} + 3|(i\%-2) $$

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

Python 2, 50 bytes

f=lambda s,i=0:s[i:]and s[(i^1)-len(s)/2]+f(s,i+1)

Try it online!

Borrowing ideas from Sisyphus, the i'th character of the output is the character at index (i^1)-len(s)/2 of the input. Here, i^1 is XOR with 1, which flips the last bit and so swaps even/odd pairs 0<->1, 2<->3, 4<->5, ...

Here's a non-recursive alternative for the same length, though it outputs a list of characters which I'm not sure is allowed.

lambda s:[s[(i^1)-len(s)/2]for i in range(len(s))]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Very nice. I think this may be optimal. \$\endgroup\$ – Sisyphus Sep 21 '20 at 10:22
3
\$\begingroup\$

C (gcc), 73 72 70 bytes

Saved 2 bytes thanks to Dominic van Essen!!!

i;l;f(char*s){for(i=1;(l=strlen(s))/i;)putchar(s[(i+l/2-++i%2*2)%l]);}

Try it online!

Inputs a string and outputs the decryption.

Explanation

Maps the index (starting at \$0\$ to the end), of the input string, \$s\$ of length \$l\$, to the correct place by shifting it over \$\frac{l}{2}+1\$ places and then back \$2\$ for odd indices. Using this \$\mod{l}\$ gives the correct index of \$s\$ for the next output character.

\$\endgroup\$
2
  • \$\begingroup\$ 70 bytes \$\endgroup\$ – Dominic van Essen Sep 21 '20 at 14:14
  • \$\begingroup\$ @DominicvanEssen Nice one, thought I had too many parentheses - thanks! :-) \$\endgroup\$ – Noodle9 Sep 21 '20 at 15:18
3
\$\begingroup\$

JavaScript (Node.js), 71 65 bytes

s=>(s.slice(l=s.length/2)+s.slice(0,l)).replace(/(.)(.)/g,'$2$1')

Try it online!

Saved 6 bytes thanks to @Shaggy.

Original 71 byte solution:

s=>(l=>s.slice(l)+s.slice(0,l))(s.length/2).replace(/(\w)(\w)/g,'$2$1')

Pretty simple stuff here - I used an inner function because I had to surround the slice calls anyway - this saves 4 bytes.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ 65 bytes \$\endgroup\$ – Shaggy Sep 21 '20 at 20:10
2
\$\begingroup\$

Brachylog, 8 bytes

ḍ↔cġ₂↔ᵐc

Try it online!

How it works

ḍ↔cġ₂↔ᵐc
ḍ        split in two halves
 ↔       reverse
  c      join
   ġ₂    group with length two
     ↔ᵐ  reverse each
       c join 
\$\endgroup\$
1
\$\begingroup\$

Python 3, 91 bytes

a=input();x=len(a)//2;b=a[x:]+a[:x];c=''
for i in range(0,len(b),2):c+=b[i+1]+b[i]
print(c)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ It should be taking input from the command line, like sys.argv \$\endgroup\$ – Smilecat Sep 21 '20 at 3:13
  • 5
    \$\begingroup\$ @Sachin usual convention in code golf is that input can be taken from STDIN, the command line, or as function parameters, and output can be to STDOUT or as a function return value, in any reasonable format. Of course, in some cases, it would make sense to restrict the input format, but consider whether or not it would improve the challenge to do so. In this case, I recommend leaving I/O as flexible as possible; generally, problems like this allow I/O as a string or list of characters as input, CL arguments, or function I/O. \$\endgroup\$ – HyperNeutrino Sep 21 '20 at 3:18
1
\$\begingroup\$

Pip, 21 bytes

RV_M(JRV(a<>#a/2)<>2)

Try it online!

Explanation

RV_M(JRV(a<>#a/2)<>2)
        (a<>#a/2)     split input into parts of size length/2
     JRV              reverse the list, and join it to string
                 <>2  split the joined string into parts of size 2
RV_M                  reverse each of those parts
                      implicit output
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 78 76 78 74 bytes

Thanks to ceilingcat for the -4!

Edit: Reverted to use addition instead of OR to avoid operator precedence issues.

Rather than splitting the string, the function starts at the middle of the string and wraps around the entire string has been processed. To flip every other character, the index inverts the 1s position of the counter.

f(s,i,j)char*s;{for(i=strlen(s),j=0;write(1,s+(i/2+j++/2*2+j%2)%i,j<i););}

Try it online!

If the program absolutely must take from the command line: 82 bytes

main(i,s,j)char**s;{for(i=strlen(*++s),j=0;write(1,*s+(i/2+j++/2*2+j%2)%i,j<i););}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ @Dingus Thank you for the heads-up. I've reverted the code to my original submission. \$\endgroup\$ – ErikF Sep 21 '20 at 7:24
1
\$\begingroup\$

Stax, 10 bytes

ü♠yαæ♠╟«ºñ

Run and debug it

What a wonderful online interpreter.

Link is to unpacked version of code.

Explanation

;%h/r$2/Frp
;           copy input
 %          get it's length
  h         halve it
   /        split input into parts of that size
    r       reverse
     $      join to string
      2/    split into parts of size 2
        F   for each element in the resulting array:
         rp reverse, and print without newline.
\$\endgroup\$
1
\$\begingroup\$

K (ngn/k), 17 bytes

,/|'0N 2#,/|2 0N#

Try it online!

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

Factor, 89 bytes

: d ( s -- s ) halves swap [ >array ] bi@ append 2 group [ reverse ] map concat >string ;

Try it online!

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

R, 64 63 bytes

m=matrix;intToUtf8(m(m(utf8ToInt(scan(,"")),,2)[,2:1],2)[2:1,])

Try it online!

Took a different approach than Dominic van Essen, who golfed down a byte. Uses matrix reshaping/indexing to do the reversing.

Ungolfed:

s <- utf8ToInt(scan(,""))		# read input and convert to a list of byte values
m <- matrix(s,,2)			# convert to a Nx2 matrix, filling down by columns
m <- m[,2:1]				# reverse the columns of the matrix (flip the halves)
m <- matrix(m,2)			# convert to an Nx2 matrix, filling down by the columns
m <- m[2:1,]				# reverse the rows (swap adjacent characters)
intToUtf8(m)				# convert back to string
\$\endgroup\$
2
  • \$\begingroup\$ Beautiful! I think you can shave-off 1 more byte like this, but it's so wonderfully simple it's difficult to imagine anything more... \$\endgroup\$ – Dominic van Essen Sep 21 '20 at 15:00
  • \$\begingroup\$ @DominicvanEssen good catch! I feel like there's some regex voodoo that could be done, but I'm not really sure how to do ^(match)(match of equal length)$ because my regex skills are paltry. But, gsub("(.)(.)","\\2\\1","<input>") does the second half of the decryption at least! \$\endgroup\$ – Giuseppe Sep 21 '20 at 15:49
1
\$\begingroup\$

bash+sed, 57 bytes

Takes input as a command line argument.

<<<"${1:${#1}/2}${1:0:${#1}/2}" sed 's/\(.\)\(.\)/\2\1/g'

Try it online!

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

Burlesque, 17 bytes

iRsa2./!!2co)<-++

Try it online!

Description:

iR               # Generate all rotations of the input string
  sa             # Duplicate and get length (which equals string length)
    2./          # Divide by two
       !!        # And grab the string that's been rotated that many times
         2co     # Split the rotated string into chunks of two
            <-   # Reverse each chunk
              ++ # Join together and implicitly output
\$\endgroup\$
0
\$\begingroup\$

Japt -P, 9 bytes

éUÊz)ò mw

Try it

éUÊz)ò mw     :Implicit input of string U
é             :Rotate right by
 UÊ           :  Length of U
   z          :  Floor divided by 2
    )         :End rotate
     ò        :Partitions of length 2
       m      :Map
        w     :  Reverse
              :Implicitly join and output
\$\endgroup\$
0
\$\begingroup\$

Charcoal, 13 bytes

⭆⪪⪫⮌⪪θ⊘Lθω²⮌ι

Try it online! Link is to verbose version of code. Explanation:

        θ       Input string
       L        Length
      ⊘         Halved
    ⪪θ          Split input string into substrings of this length
   ⮌            Reverse
  ⪫      ω      Join together
 ⪪        ²     Split into substrings of length 2
⭆               Map over substrings and join
            ι   Current substring
           ⮌    Reversed
                Implicitly print
\$\endgroup\$
0
\$\begingroup\$

Retina 0.8.2, 36 bytes

((.)+?)((?<-2>.)+)$
$3$1
(.)(.)
$2$1

Try it online! Explanation: The first stage uses a .NET balancing group to match as few characters as possible into $1 while still matching the same number of characters into $3. $#2 increments for each character matched into $1 and decrements for each character matched into $3 but it cannot decrement below zero, so $1 is forced to consume the first half of the string to allow the end of the string to be reached. The second stage then flips pairs of adjacent characters. (Also ASCII art bewbs.)

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

MathGolf, 10 bytes

h½/xy2/mx~

Try it online.

Explanation:

h           # Get the length of the (implicit) input-string (without popping)
            #  i.e. "HGJILKBADCFE" → "HGJILKBADCFE" and 12
 ½          # Halve this length
            #  → "HGJILKBADCFE" and 6
  /         # Split the string into parts of that size
            #  → ["HGJILK","BADCFE"]
   x        # Reverse this pair
            #  → ["BADCFE","HGJILK"]
    y       # Join it back together to a string
            #  → "BADCFEHGJILK"
     2/     # Split it into parts of size 2
            #  → ["BA","DC","FE","HG","JI","LK"]
       m    # Map over each pair:
        x   #  Reverse the pair
            #  → ["AB","CD","EF","GH","IJ","KL"]
         ~  # Pop and push all strings separated to the stack
            #  → "AB", "CD", "EF", "GH", "IJ", and "KL"
            # (after which the entire stack joined together is output implicitly)
            #  → "ABCDEFGHIJKL"
\$\endgroup\$
0
\$\begingroup\$

Red, 89 bytes

func[s][move/part s tail s(length? s)/ 2
rejoin collect[foreach[b a]s[keep rejoin[a b]]]]

Try it online!

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

Lua, 67 bytes

a=...b=#a//2print(((a:sub(b+1)..a:sub(1,b)):gsub('(.)(.)','%2%1')))

Try it online!

First, string is cut in two using sub functions and then concatenated back in reverse order. Then, gsub is used to swap pairs of characters.

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

Wolfram Language (Mathematica), 64 51 bytes

#[[#+UnitStep@#&@Array[#+(-1)^#&,L=Tr[1^#],-L/2]]]&

Try it online!

Port of Sisyphus's Python solution

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

CJam, 13 bytes

q2/::\_,2//:\

Try it online!

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

Perl 5 -pF, 40 bytes

for$p("."x(@F/2),"."){s/($p)($p)/$2$1/g}

Try it online!

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

Poetic, 472 bytes

DECODING THINGS:A BRIEFING
o,o,hello!i am agent Q
nah,Q`s chosen by an infamous phoney
a misprint!oh,sorry!am i sorry
i am agent J.W,tech/A.I hacker
i see a piece o code,i am trying at a means on how i decode it
what i am doing:i am laying all A-Z clearly along a pathway
midway,put in zeros(O,O)cause J.W needs it to split em
i shift em in tandem,i get B,A
lastly,if it leaves you a letter,it is moved
o,then i am doing A-Z again,it is taken to a shift
ah ha!spying is EZ

Try it online!

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