How the encoding works

Given a list of bits:

  • Hold a prime (starting with 2)
  • Have a list
  • For each bit in the input
    • If it's the same as the previous bit, add the prime you're holding to the list
    • If it's different, hold the next prime and add that to the list
  • Return the product of all the numbers in your list
  • For the first bit, assume the previous bit was 0

Note: these steps are for illustration purposes only, you are not required to follow them.


Input: 001
hold 2

0:         add 2 to the list
0:         add 2 to the list
1: hold 3, add 3 to the list

list: 2,2,3
Output: 12

Input: 1101
hold 2

1: hold 3, add 3 to the list
1:         add 3 to the list
0: hold 5, add 5 to the list
1: hold 7, add 7 to the list

list: 3,3,5,7
Output: 315

Some more examples:

000000000 -> 512
111111111 -> 19683
010101010 -> 223092870
101010101 -> 3234846615
011101101 -> 1891890
000101101010010000 -> 3847834029582062520


Write an encoder and a decoder for this encoding method.

(The decoder reverses the process of the encoder).

Input / Output

  • The encoder can take input in any reasonable format

  • The encoder must output either an integer or a string

  • The decoder must take input in the same format that the encoder outputs

  • The decoder must output the same format that the encoder takes as input

In other words decoder( encoder( input ) ) === input


  • The decoder may assume that its input is decodable
  • Your answer only has to deal with integers that your language can natively support without using (long, bigInt, etc.), be reasonable, if you language only supports ints up to 1, maybe reconsider posting an answer


Your score is the sum of the lengths in bytes of the encoder and decoder.

If you need to import a module, the import can be counted only once provided that your encoder and decoder can coexist in the same file and be reused (like functions).

Default loopholes are forbidden.

This is so the shortest score for every language wins.

  • \$\begingroup\$ Is that last example mandatory, or can we limit the output to up to 64 bits (2^63-1 / 9223372036854775808)? \$\endgroup\$ Commented Apr 26, 2018 at 12:03
  • 1
    \$\begingroup\$ @KevinCruijssen No, your answer only has to work for integers that your language can handle. \$\endgroup\$ Commented Apr 26, 2018 at 12:06
  • 1
    \$\begingroup\$ @KevinCruijssen *handle natively without libraries of bigints, i'll clarify \$\endgroup\$ Commented Apr 26, 2018 at 13:07

10 Answers 10


05AB1E, 13 bytes

Encoder, 8 bytes


Try it online!


0ì          # prepend 0 to input
  ¥         # calculate deltas
   Ā        # truthify each
    η       # calculate prefixes
     O      # sum each
      Ø     # get the prime at that index
       P    # product

Decoder, 5 bytes


Try it online!


Ò       # get prime factors of input
 .Ø     # get their indices among the primes
   É    # check for oddness
    J   # join

Jelly, 17 bytes

Encoder (10 bytes):


Try it online!

Decoder (7 bytes):


Try it online!



0;IA+\‘ÆNP - Link: list of integers (1s and 0s)  e.g. [1,1,1,1,0]
0;         - prepend a zero                           [0,1,1,1,1,0]
  I        - incremental differences                  [1,0,0,0,-1]
   A       - absolute values                          [1,0,0,0,1]
    +\     - cumulative reduce with addition          [1,1,1,1,2]
      ‘    - increment each of the results            [2,2,2,2,3]
       ÆN  - get the nth prime for each result        [3,3,3,3,5]
         P - product of the list                      405


ÆEĖŒṙḂ¬ - Link: integer         e.g. 405
ÆE      - prime exponent array       [0,4,1] (representing 2^0*3^4*5^1)
  Ė     - enumerate                  [[1,0],[2,4],[3,1]]
   Œṙ   - run-length decode          [2,2,2,2,3]
     Ḃ  - bit (mod 2)                [0,0,0,0,1]
      ¬ - logical NOT                [1,1,1,1,0]

JavaScript (ES6), 130 bytes

I/O: array of bits ↔ integer

Encoder, 71 bytes


Try it online!

Decoder, 59 bytes


Try it online!


Java 10, 209 bytes

Encoder, 124 bytes

s->{long p=48,P=2,r=1,n,i;for(int c:s.getBytes()){if(p!=(p=c))for(n=0;n<2;)for(n=++P,i=2;i<n;n=n%i++<1?0:n);r*=P;}return r;}

Try it online.


s->{                // Method with String parameter and long return-type
  long p=48,        //  Previous character, starting at '0'
       P=2,         //  Current prime, starting at 2
       r=1,         //  Result, starting at 1
       n,i;         //  Temp-integers
  for(int c:s.getBytes()){
                    //  Loop over the digits of the input-String as bytes
    if(p!=(p=c))    //   If the current and previous digits are different
      for(n=0;      //    Reset `n` to 0
          n<2;)     //    And loop as long as `n` is still 0 or 1
        for(n=++P,  //     Increase `P` by 1 first with `++P`, and set `n` to this new `P`
                    //     Check of the current `n` is a prime
                    //     If it remains the same it's a prime, if it becomes 0 or 1 not
    r*=P;}          //   Multiply the result by the current prime `P`
  return r;}        //  Return the result

Decoder, 85 bytes

n->{var r="";for(long P=2,f=0,i=1;++i<=n;)for(;n%i<1;n/=P=i)r+=i!=P?f^=1:f;return r;}

Try it online.


n->{                // Method with long parameter and String return-type
  var r="";         //  Result-String, starting empty
  for(long P=2,     //  Current prime, starting at 2
      f=0,          //  Flag integer, starting at 0
      i=1;++i<=n;)  //  Loop `i` in the range [2,`n`]
    for(;n%i<1;     //   Inner loop over the prime factors of `n`
        n/=P=i)     //     After every iteration: divide `n` by `i`,
                    //     and set `P` to `i` at the same time
      r+=i!=P?      //    If `i` and `P` are not the same
          f^=1      //     Append the opposite of the flag `f` (0→1; 1→0)
         :          //    Else:
          f;        //     Append the flag `f`
  return r;}        //  Return the result
  • \$\begingroup\$ You can save 2 bytes by changing long to int. \$\endgroup\$ Commented Apr 26, 2018 at 19:15

Husk, 18 bytes

Encoder, 11 bytes


Try it online!

Decoder, 7 bytes


Try it online!

How they work


Πmo!İp→∫Ẋ≠Θ – Full program. Takes input from the first CLA, outputs to STDOUT.
          Θ – Prepend a default element (0 in this case).
        Ẋ≠  – Map over pairs of adjacent elements with ≠ (not equals). In Husk,
              some operators return other useful things than just boolean values.
              Here, ≠ returns the absolute difference between its two arguments.
       ∫    – Cumulative sums.
 mo         – Map the following function over the list of sums:
    İp        – Yield the infinite list of primes.
   !  →       – And index into it with the current sum incremented.
Π           – Take the product.


mȯ¬%2ṗp – Full program.
      p – Prime factorization.
mȯ      – Map the following function over the list of factors:
     ṗ    – Retrieve the index in  the list of primes.
   %2     – Modulo 2.
  ¬       – Logical NOT.

Python 2, 234 193 174 bytes

Encoder, 116 101 97 bytes:

Uses Wilson's theorem.

while i:
 if P%n:t=(i+[x]).index(x);i=i[t:];r*=n**t;x^=1
print r

Try it online!

Decoder, 118 92 77 bytes:

 while i%n<1:r+=x,;i/=n
print r

Try it online!


J, 34 bytes

Heavily inspired by Jonathan Allan's Jelly solution!

Encoder: 23 bytes


Try it online!

                    0,]  NB. prepend 0 to the input
             2  -~/\     NB. find the differences
              |@         NB. and their absolute values 
        [:+/\            NB. running sums
    [:p:                 NB. n-th prime
[:*/                     NB. product  

I don't like those many cap forks [: - it should be golfable.

Decoder: 11 bytes


Try it online!

        q:    NB. prime factorization
  [:_1&p:      NB. find the number of primes smaller than n
2|             NB. modulo 2 

Jelly, 15 bytes

Encoder, 9 bytes


Try it online!

Decoder, 6 bytes


Try it online!


C (gcc), 180 184 bytes

  • Added four bytes so that output formats match.

102 bytes -- Encoder


Try it online!

82 bytes -- Decoder


Try it online!

  • \$\begingroup\$ @AsoneTuhid Sorry, misread. \$\endgroup\$ Commented Apr 26, 2018 at 11:31
  • \$\begingroup\$ @AsoneTuhid Now added a decoder. Hopefully compliant now. \$\endgroup\$ Commented Apr 26, 2018 at 11:53
  • \$\begingroup\$ @ovs True; thanks for your remark. \$\endgroup\$ Commented Apr 26, 2018 at 14:21

Gol><>, 29 + 39 = 68 bytes

Encoder, 29 bytes


Try it online!

Decoder, 39 bytes


Try it online!

How these work



021                            Setup the stack as [last bit, current prime, current output]
   IEh                         Take input as int; if EOF, print top as number and halt
      {$:}-Q          |        If the next bit is different from the last bit...
            $                    Move the prime to the top
             T      t            Loop indefinitely...
              P:SP?!               Increment; if prime, skip `t` i.e. break
                     $           Move the prime to the correct position
                       1k*     Multiply the prime to the output
                          3R!  Skip 3 next commands (the init part)
                               Loop the entire program until EOF




02I                  Setup the stack as [last bit, current prime, encoded]
   :MZ;              If encoded == 1, halt
       :2k%          Compute encoded modulo prime
           :z}       Store NOT of the last at the bottom of the stack
              Q...|  Same as encoder's next-prime loop
1k,                  Divide encoded by prime (assume it is divisible)
   {{                Pull out the two bits at the bottom
     -z              Compute the next bit
       :N}           Print as number with newline, and move to the bottom
          3R!        Skip 3 init commands
                     Loop the entire program until finished

It'd be better if I could golf down the next-prime loop...


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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