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

| improve this answer | |
\$\endgroup\$
  • 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 at 4:04
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)
| improve this answer | |
\$\endgroup\$
  • 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 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 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

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ @JoKing Thanks Jo but my ancient APL+WIN interpreter does not have the ⍨ operator nor does it support trains \$\endgroup\$ – Graham Sep 21 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 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 at 17:16
  • \$\begingroup\$ Okay thanks for correcting me. Thumbs up for the answer. \$\endgroup\$ – jimfan Oct 4 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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ One byte shorter: Try it online! \$\endgroup\$ – pajonk Sep 21 at 11:32
  • \$\begingroup\$ @pajonk Yes! Thankyou! \$\endgroup\$ – Dominic van Essen Sep 21 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 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 at 9:21
4
\$\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 $_.)

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ @Sachin To take input from the command line you could do something like this. \$\endgroup\$ – Dingus Sep 21 at 4:46
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.

| improve this answer | |
\$\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) $$

| improve this answer | |
\$\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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Very nice. I think this may be optimal. \$\endgroup\$ – Sisyphus Sep 21 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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ 70 bytes \$\endgroup\$ – Dominic van Essen Sep 21 at 14:14
  • \$\begingroup\$ @DominicvanEssen Nice one, thought I had too many parentheses - thanks! :-) \$\endgroup\$ – Noodle9 Sep 21 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.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ 65 bytes \$\endgroup\$ – Shaggy Sep 21 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 
| improve this answer | |
\$\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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ It should be taking input from the command line, like sys.argv \$\endgroup\$ – Smilecat Sep 21 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 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
| improve this answer | |
\$\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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ @Dingus Thank you for the heads-up. I've reverted the code to my original submission. \$\endgroup\$ – ErikF Sep 21 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.
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

K (ngn/k), 17 bytes

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

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Factor, 89 bytes

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

Try it online!

| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$
  • \$\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 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 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!

| improve this answer | |
\$\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
| improve this answer | |
\$\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
| improve this answer | |
\$\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
| improve this answer | |
\$\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.)

| improve this answer | |
\$\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"
| improve this answer | |
\$\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!

| improve this answer | |
\$\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.

| improve this answer | |
\$\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

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

CJam, 13 bytes

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

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -pF, 40 bytes

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

Try it online!

| improve this answer | |
\$\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!

| improve this answer | |
\$\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.