12
\$\begingroup\$

The Problem:

Two enemy secret agents have devised a wonderful (for you) method of communication!

Here’s how the encryption process works:

1) Take the ascii equivalents of each letter. (No spaces, numbers, or punctuation are sent)

2) For each letter in the message, the ascii equivalent of it and the letter after it (If it exists, if it doesn’t, it should be considered 0), are multiplied (this product is stored in an array/list) and summed (this number is also stored in a different list).

3) The two lists (of sums and products) are joined together (the sums list, then the multiples list, into the same array) and transmitted.

You need to write the smallest program able to reverse this process and decrypt messages sent in this format!

Example Input and Output Pairs:

[173, 209, 216, 219, 198, 198, 225, 222, 208, 100, 7272, 10908, 11664, 11988, 9657, 9657, 12654, 12312, 10800, 0] -> “HelloWorld”
[131, 133, 164, 195, 197, 99, 4290, 4422, 6499, 9506, 9702, 0] -> “ABCabc”

This is , so the smallest solution in bytes wins.

Error messages are allowed.

Your program can be given either a list/1-dimensional array or a comma-separated string, if you specify in your submission. The default is an array/list.

\$\endgroup\$
  • 1
    \$\begingroup\$ Why is the list of multiples even there? Just the sums is enough information. \$\endgroup\$ – orlp Jan 7 '18 at 2:04
  • 1
    \$\begingroup\$ @orlp maybe to allow more golfing opportunities? :) \$\endgroup\$ – Jonathan Allan Jan 7 '18 at 2:06
  • 1
    \$\begingroup\$ @orlp oh no, you spoiled the fun! \$\endgroup\$ – Erik the Outgolfer Jan 7 '18 at 10:53
  • \$\begingroup\$ @JonathanAllan is correct, partially. I wanted the two secret agents to appear super stupid, so that they add unnecessary parts to their “code”. It also adds some more possible programs that can come out. \$\endgroup\$ – iPhoenix Jan 7 '18 at 13:25
  • \$\begingroup\$ @orlp Just the multiples isn't enough, right? \$\endgroup\$ – ericw31415 Jan 7 '18 at 18:55

18 Answers 18

5
\$\begingroup\$

Husk, 7 6 bytes

mcĠ≠←½

Try it online! According to the documentation the leading m should not be needed, but there seems to be a bug currently.

Edit: -1 byte thanks to Zgarb!

Explanation:

     ½ -- split input list into half
    ←  -- take first list
  Ġ≠   -- subtract each list element from the previous one
mc     -- convert list of code points to string
\$\endgroup\$
  • \$\begingroup\$ I think `- can be . The behavior of c indeed looks like a bug. \$\endgroup\$ – Zgarb Jan 7 '18 at 10:47
  • \$\begingroup\$ @Zgarb That's a practical way to implement unequal. Is this documented somewhere? \$\endgroup\$ – Laikoni Jan 7 '18 at 11:08
  • \$\begingroup\$ It's on the Semantics page of Husk Wiki. \$\endgroup\$ – Zgarb Jan 7 '18 at 11:12
  • 1
    \$\begingroup\$ It seems you changed your explanation, but not the actual code snippet itself. :) \$\endgroup\$ – iPhoenix Jan 7 '18 at 18:51
  • \$\begingroup\$ @iPhoenix Thanks, I correted it. \$\endgroup\$ – Laikoni Jan 7 '18 at 19:50
8
\$\begingroup\$

brainfuck, 66 bytes

,[>>>+<[-<+>>-<]<[->+<],]>[<<,>>[-<+>]<-]<<<[>[-<->>+<]<<]>.>>[.>]

Input is the encrypted string. Assumes infinite sized cells and 0 on EOF.

How it Works:

,[>>>+<[-<+>>-<]<[->+<],] Gets input and the number of characters divided by 2
>[<<,>>[-<+>]<-]<<< Remove the second half of the string (the multiplication part)
[>[-<->>+<]<<] Subtract each character from the previous one, while keeping a copy of the previous one.
>.>>[.>] Print the characters
\$\endgroup\$
5
\$\begingroup\$

Haskell, 45 35 bytes

map toEnum.scanr1(-).fst.span(<245)

Try it online!

Explanation

  • fst.span(<245) takes all numbers from the beginning of the list that are smaller than 245. Those are only the numbers from the summation part, because the largest possible summation is z + z = 122 + 122 = 244, and the smallest possible product is A * A = 65 * 65 = 4225.
  • scanr1(-) takes the last value of the list and uses it as initial accumulator. Then from back to front each element of the list is subtracted by the current accumulator, and the result is used as the next accumulator and and added to a list.
  • map toEnum replaces each number in the list with the corresponding character to recreate the string.
\$\endgroup\$
3
\$\begingroup\$

Jelly, 9 bytes

œs2ḢUạ\ỌU

Try it online! or Check both test cases.

Alternative.

Explanation

œs2ḢUạ\ỌU || Full program.

œs2       || Split into two parts, with the first one being longer if necessary.
   Ḣ      || Get the head (first element).
    U     || Reverse.
     ạ\   || Cumulative reduce by subtraction.
       Ọ  || Convert from code points to characters.
        U || And reverse again.
\$\endgroup\$
3
\$\begingroup\$

Python 2, 72 bytes

a=input();p=0;r=''
for v in a[len(a)/2-1::-1]:r=chr(v-p)+r;p=v-p
print r

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 2, 92 bytes

lambda C:"".join(chr(sum((-1)**i*C[j+i]for i in range(len(C)/2-j)))for j in range(len(C)/2))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Jelly, 11 bytes

œs2Ḣḅ-$ÐƤAỌ

A monadic link taking a list of integers and returning a list of characters.

Try it online!

How?

œs2Ḣḅ-$ÐƤAỌ - Link: list of integers     e.g. [210,211,201,101,10989,11100,10100,0]
  2         - literal two                     2
œs          - split into equal parts          [[210,211,201,101],[10989,11100,10100,0]]
   Ḣ        - head                            [210,211,201,101]
       ÐƤ   - for postfixes:                  [210,211,201,101],[211,201,101],[201,101],[101]
      $     -   last two links as a monad:
     -      -     literal minus one           -1
    ḅ       -     convert from base           -99              ,111          ,-100      ,101
         A  - absolute value (vectorises)     [99,111,100,101]
          Ọ - convert to ordinal (vectorises) "code"
\$\endgroup\$
1
\$\begingroup\$

Pyt, 60 bytes

←ĐĐŁ₂⁻⦋⇹ĐŁřĐŁ₂>*ž0`ŕĐĐŁ⁻⦋3ȘĐ4Ș3Ș4Ș÷⇹ĐŁřĐŁ<*žĐŁ⁻łŕ⇹Đ3Ș⇹÷Á↔áƇǰ

Takes a list of integers and returns a string of characters.

Explanation:

←ĐĐŁ₂⁻⦋⇹          Gets the ASCII code of the last character
ĐŁřĐŁ₂>*ž         Gets the list of products and removes the 0 from the end of the list
0`ŕ ...  ł        Loops (0 is there so that the length can be removed from the stack)
ĐĐŁ⁻⦋              Gets the last product
3ȘĐ4Ș3Ș4Ș÷        Divides by the last ASCII code obtained
⇹ĐŁřĐŁ<*ž         Removes the last element from the array
ĐŁ⁻ł              Gets the length of the array - 1 (if 0, then exit loop - the last entry still has to be processed)
ŕ⇹Đ3Ș⇹÷           Divides the remaining product by the last ASCII code obtained           
Á↔á               Converts to array of ints
Ƈǰ                Converts to string of ASCII characters

Try it online!

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

JavaScript (ES6), 80 bytes

a=>String.fromCharCode(...eval(`for(a.splice(i=a.length/2);--i;a[i-1]-=a[i])a`))

f=

a=>String.fromCharCode(...eval(`for(a.splice(i=a.length/2);--i;a[i-1]-=a[i])a`))

console.log(
    f([173, 209, 216, 219, 198, 198, 225, 222, 208, 100, 7272, 10908, 11664, 11988, 9657, 9657, 12654, 12312, 10800, 0]),
    f([131, 133, 164, 195, 197, 99, 4290, 4422, 6499, 9506, 9702, 0])
)

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

VB Script - 74 71 bytes

( I managed to reduce from 74 to 71 by using While..Wend instead of Do..Loop)

The input is in an array a(), the output is in string d

d="":p=0:n=(UBound(a)+1)/2:While n>0:n=n-1:t=a(n)-p:d=Chr(t)&d:p=t:Wend

Explanation

d=""          '// initialize the output string
p=0          '// initialize the ansii of following char (working back from last char)
n=(Ubound(a)+1)/2 '// the index of the last summed pair + 1 (base 0)
While n>0    '// begin loop working back from last summed pair
n=n-1        '// move back 1 char
t=a(n)-p     '// calculate the ansii by subtracting the ansii of following char
d=Chr(t)&d   '// prepend the char to output
p=t          '// this char becomes the following char for next
Wend         '// repeat etc.

I tested this in a vbscript file with the above code wrapped as a function:

dim s
Dim arr()
s = Split("173, 209, 216, 219, 198, 198, 225, 222, 208, 100, 7272, 10908, 11664, 11988, 9657, 9657, 12654, 12312, 10800, 0", ",")
ReDim arr(UBound(s))
Dim x 
For x = 0 To UBound(s)
    arr(x) = cint(s(x))
Next 

msgbox "=" & d(arr)



Private Function d(a())
d="":p=0:n=(UBound(a)+1)/2:While n>0:n=n-1:t=a(n)-p:d=Chr(t)&d:p=t:Wend
End Function
\$\endgroup\$
1
\$\begingroup\$

Clean, 96 81 78 77 bytes

zero is the null character.
I could save another byte if Clean wasn't so picky about literal nulls in the source file.

import StdEnv
f=init o foldr(\a t=[toChar a-t!!0:t])[zero]o takeWhile((>)245)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Anonymous functions are in general acceptable, so if you want you can drop the f=. \$\endgroup\$ – Laikoni Jan 9 '18 at 14:25
  • \$\begingroup\$ @Laikoni I'm not sure about the validity of that in this case, because it needs parenthesies to be used inline, and f= is the shortest assignment, so a minimal invocation adds two anyway. \$\endgroup\$ – Οurous Jan 9 '18 at 19:07
1
\$\begingroup\$

Perl 5, 39 + 2 (-ap) = 41 bytes

$#F/=2;$\=chr($p=-$p+pop@F).$\while@F}{

Try it online!

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

C (gcc), 90 89 bytes

  • Saved a byte thanks to ceilingcat; s+=(i%2?-1:1)*... <~> s-=~(i%2*-2).
D(C,l,j,s,i)int*C;{for(j=~0;++j<l/2;putchar(s))for(s=i=0;i+j<l/2;)s-=~(i%2*-2)*C[i+++j];}

Try it online!

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

Standard ML (MLton), 85 84 82 bytes

fun!(x::r)=if x>244then[]else(fn z::s=>x-z::z::s|_=>[x])(!r);implode o map chr o!;

Try it online!

Ungolfed:

fun g (x::r) =
   if   x > 244
   then []
   else case g r of
          z::s => x-z :: z :: s
        |  []  => [x]

val f = implode o map chr o g

Try it online!

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

Perl 6,  43 39  35 bytes

{[~] [R,](produce *R-*,[R,] .[^*/2])».chr}

Test it

{[~] [R,]([\[&(*R-*)]] [R,] .[^*/2])».chr}

Test it (does the same as above)

{[~] [R,]([\R[&(*R-*)]] .[^*/2])».chr}

Test it

{[R~] [\R[&(*R-*)]](.[^*/2])».chr}

Test it

Explanation:

{[R~] [\R[&(*R-*)]](.[^*/2])».chr}

{                                }      # block lambda with parameter `$_`

      [\R[&(*R-*)]](.[^*/2])            # turn sums back into ordinals (reversed)

                    .[^*/2]             # first half of `$_` (implicit method call)
            *R-*                        # lambda, reverse of *-*
         [&(    )]                      # use it as an infix operator
                                        # (same as R- except left associative)
        R                               # reverse arguments and associativity
                                        # (same as - except right associative)
      [\          ](       )            # produce values `[\+] 1,2,3` => `(1,3,6)`
                                        # uses associativity to determine direction
                                        # `[\**] 1,2,3` => `(3,8,1)`

                            ».chr       # call `.chr` method on all values
                                        # (possibly concurrently)

 [R~]                                   # concatenate in reverse
                                        # (shorter than `join '', reverse …`)
\$\endgroup\$
0
\$\begingroup\$

05AB1E, 9 bytes

2ä¬Å«-}çJ

Try it online!

Explanation

2ä        # Split input list in two (equal if possible) parts.
  ¬       # Push head(a).
   Å«-}   # Cumulative reduce the list by subtraction (from the right).
       ç  # Convert each integer in the list to its corresponding ASCII char.
        J # Join list together to string.
\$\endgroup\$
  • \$\begingroup\$ You don't need the Join. \$\endgroup\$ – Shaggy Jan 17 '19 at 17:08
  • \$\begingroup\$ @Shaggy ç does not implicitly turn the list of characters into a string though. If I understand the problem correctly, the program needs to output a string and not a list of characters. \$\endgroup\$ – Wisław Jan 17 '19 at 18:22
0
\$\begingroup\$

Japt, 12 bytes

There has to be a shorter way to get the first half of the array ...

¯UÊz)Ôån Ômd

Try it

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

Python 2, 70 bytes

l,j,s=input(),0,'';n=len(l)/2
while n:n-=1;j=l[n]-j;s=chr(j)+s
print s

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.