Densamente empaquetado decimal (DPD) a decimal

26

Para los fanáticos de nandgame: ¡prueba DPD a decimal en puertas lógicas también!

Fondo

El decimal denso (DPD) es una forma de almacenar eficientemente dígitos decimales en binario. Almacena tres dígitos decimales (000 a 999) en 10 bits, que es mucho más eficiente que el BCD ingenuo (que almacena un dígito en 4 bits).

Anotaciones

  • Las letras minúsculas aa ison los bits que se copian en la representación decimal.
  • 0y 1son los bits exactos en los patrones de bits de entrada o salida.
  • x los bits se ignoran en la conversión.

Tabla de conversión

La siguiente es la tabla de conversión de 10 bits de DPD a tres dígitos decimales. Cada dígito decimal se representa como binario de 4 bits (BCD). Ambas partes se escriben de izquierda a derecha desde el dígito más significativo al menos.

Bits                 =>  Decimal         (Digit range)
a b c d e f 0 g h i  =>  0abc 0def 0ghi  (0-7) (0-7) (0-7)
a b c d e f 1 0 0 i  =>  0abc 0def 100i  (0–7) (0–7) (8–9)
a b c g h f 1 0 1 i  =>  0abc 100f 0ghi  (0–7) (8–9) (0–7)
g h c d e f 1 1 0 i  =>  100c 0def 0ghi  (8–9) (0–7) (0–7)
g h c 0 0 f 1 1 1 i  =>  100c 100f 0ghi  (8–9) (8–9) (0–7)
d e c 0 1 f 1 1 1 i  =>  100c 0def 100i  (8–9) (0–7) (8–9)
a b c 1 0 f 1 1 1 i  =>  0abc 100f 100i  (0–7) (8–9) (8–9)
x x c 1 1 f 1 1 1 i  =>  100c 100f 100i  (8–9) (8–9) (8–9)

Tarea

Convierta 10 bits de DPD a 3 dígitos de decimal.

Casos de prueba

DPD           Decimal
0000000101    005
0001100011    063
0001111001    079
0000011010    090
0001011110    098
1010111010    592
0011001101    941
1100111111    879
1110001110    986
0011111111    999
1111111111    999  * Output is same regardless of the `x` bits

Entrada

El formato de entrada predeterminado es una lista de 10 bits. Los bits deben seguir el orden exacto anterior o al revés. Puede optar por utilizar una cadena equivalente o una representación entera en su lugar. A diferencia de mis otros desafíos, reordenar o usar estructuras anidadas no está permitido .

Para la entrada [1, 1, 0, 0, 0, 1, 0, 1, 0, 0], se permiten los siguientes formatos:

  • Lista de bits: [1, 1, 0, 0, 0, 1, 0, 1, 0, 0]
  • Cuerda: "1100010100"
  • Entero binario: 788o0b1100010100
  • Entero decimal: 1100010100
  • Invertido: [0, 0, 1, 0, 1, 0, 0, 0, 1, 1]e invertido en cualquier otro formato anterior

Los siguientes formatos NO están permitidos:

  • Reordenamiento arbitrario de bits: [0, 0, 0, 0, 0, 1, 1, 1, 0, 1]
  • Estructuras anidadas: [[1, 1, 0], [0, 0, 1], [0, 1, 0, 0]]o[0b110, 0b001, 0b0100]

Salida

El formato de salida predeterminado es una lista de 3 dígitos decimales. Cada dígito debe representarse como 0 a 9, ya sea un entero o un carácter. Como en la entrada, puede elegir la representación de cadena o de enteros. Si elige la representación de enteros, se pueden omitir los ceros a la izquierda.

Criterio de puntuación y ganador

Aplican reglas estándar de . El programa o función más corto en bytes para cada idioma gana.

Bubbler
fuente

Respuestas:

12

JavaScript (ES6), 112 bytes

Todo el crédito para esta versión más corta va a @nwellnhof.

Toma la entrada como un entero. Devuelve una matriz de tres dígitos decimales.

n=>[(x=n>>4,y=x>>3,q=n/2&55,p=q%8)>5&&q-39?8|y&1:y,(p&5^5?x&6:q-23?8:y&6)|x&1,(p<5?p*2:p<6?x&6:p%q<7?y&6:8)|n&1]

Pruébalo en línea!


JavaScript (ES6), 118117 bytes

Toma la entrada como un entero. Devuelve una matriz de tres dígitos decimales.

n=>[(x=n>>4&7,y=n>>7,p=n/2&7)>5&&p<7|x/2^2?8|y&1:y,(p<7?p-5?x:8:x/2^1?8:y&6)|x&1,(p<5?p*2:p<6?x&6:p<7|x<2?y&6:8)|n&1]

Pruébalo en línea!

¿Cómo?

En lugar de intentar aplicar el algoritmo 'oficial', este código se basa en algún tipo de ingeniería inversa de los patrones que se pueden encontrar en los resultados esperados.

Dado el entero de entrada n , calculamos:

x=n16mod8y=n128p=n2mod8

Ejemplo: primer dígito (cientos)

x     | 0                | 1                | 2                | 3               
n & 1 | 0101010101010101 | 0101010101010101 | 0101010101010101 | 0101010101010101
p     | 0011223344556677 | 0011223344556677 | 0011223344556677 | 0011223344556677
------+------------------+------------------+------------------+-----------------
y = 0 | 0000000000008888 | 0000000000008888 | 0000000000008888 | 0000000000008888
y = 1 | 1111111111119999 | 1111111111119999 | 1111111111119999 | 1111111111119999
y = 2 | 2222222222228888 | 2222222222228888 | 2222222222228888 | 2222222222228888
y = 3 | 3333333333339999 | 3333333333339999 | 3333333333339999 | 3333333333339999
y = 4 | 4444444444448888 | 4444444444448888 | 4444444444448888 | 4444444444448888
y = 5 | 5555555555559999 | 5555555555559999 | 5555555555559999 | 5555555555559999
y = 6 | 6666666666668888 | 6666666666668888 | 6666666666668888 | 6666666666668888
y = 7 | 7777777777779999 | 7777777777779999 | 7777777777779999 | 7777777777779999

x     | 4                | 5                | 6                | 7               
n & 1 | 0101010101010101 | 0101010101010101 | 0101010101010101 | 0101010101010101
p     | 0011223344556677 | 0011223344556677 | 0011223344556677 | 0011223344556677
------+------------------+------------------+------------------+-----------------
y = 0 | 0000000000008800 | 0000000000008800 | 0000000000008888 | 0000000000008888
y = 1 | 1111111111119911 | 1111111111119911 | 1111111111119999 | 1111111111119999
y = 2 | 2222222222228822 | 2222222222228822 | 2222222222228888 | 2222222222228888
y = 3 | 3333333333339933 | 3333333333339933 | 3333333333339999 | 3333333333339999
y = 4 | 4444444444448844 | 4444444444448844 | 4444444444448888 | 4444444444448888
y = 5 | 5555555555559955 | 5555555555559955 | 5555555555559999 | 5555555555559999
y = 6 | 6666666666668866 | 6666666666668866 | 6666666666668888 | 6666666666668888
y = 7 | 7777777777779977 | 7777777777779977 | 7777777777779999 | 7777777777779999

Algoritmo:

  • Si p<6 6 , tenemos d=y
  • Si p=6 , tenemos d=8+(ymod2)
  • Si p=7 AND (x<4 OR x>5) , tenemos d=8+(ymod2)
  • Si p=7 AND (x=4 OR x=5) , tenemos d=y

Como código JS:

p > 5 && p < 7 | x / 2 ^ 2 ? 8 | y & 1 : y
Arnauld
fuente
1
Su enfoque es similar a mi respuesta C que usa otra variable temporal. Después de jugar un poco más a mi solución inicial de C, un puerto a JavaScript da como resultado 112 bytes .
nwellnhof el
10

Python 3 , 229 ... 97 96 bytes

lambda a:[[a&6,a>>4&6,a>>7&6,8][b"  eW7B]Oys"[~a&8or~a&6or~6|a>>4]%x&3]|a>>x%9&1for x in[7,4,9]]

Pruébalo en línea!

-4 bytes por @xnor

-6 bytes por @nwellnhof

Formateado:

h = lambda a:[
    [a&6, a>>4&6, a>>7&6, 8][              List to take high bits from
        b"  eW7B]Oys"[                     10 char string; where to get high bits for
                                             indicator values 1-8. 0th,1st chars not used.
            ~a&8 or ~a&6 or ~6|a>>4]       Compute indicator (by @nwellnhof)
        %x&3]                              High bits of each digit
    | a >> x%9 & 1                         bitwise OR with low bit of each digit
    for x in [7,4,9]]

Explicación

Debido a que originalmente quería implementar esto en Jelly, adopto un enfoque diferente de la mayoría de las respuestas aquí, que es simple y quizás adecuado para un lenguaje de golf. Aunque la función de golf toma un número entero, deje que la entrada como una lista de bits sea [a0,a1,...,a9]. Entonces podemos derivar tres valores de la entrada

  • Los bits bajos [a2,a5,a9]: siempre serán los bits bajos de [d0,d1,d2]respectivamente.
  • Los bits altos [2*a0a1,2*a3a4,2*a7a8,8]: los bits altos de cada dígito serán uno de estos.
  • Los bits indicadores [a3,a4,a5,a7,a8], que determinan cómo obtener los bits altos de cada dígito. Calculamos el indicador (entre 1 y 8) de la siguiente manera:
    • Si a5 == 0, el indicador es 8 (originalmente 0, pero usar 8 guarda un byte)
    • Si a3 y a4, el indicador es 6 - 2 * a3a4
    • De lo contrario, el indicador es 2 * a7a8 + 1 (realmente calculado como un número negativo).

Luego, el enésimo dígito se puede calcular con elegancia como high_bits[arr[indicator][n]] | low_bits[n]en la tabla a continuación, que se comprime en una cadena.

arr = [
    [0,1,2],
    [3,1,2],
    [1,3,2],
    [2,1,3],
    [2,3,3],
    [3,2,3],
    [3,3,2],
    [3,3,3]
]
lirtosiast
fuente
1
Puede usar una cadena b"..."de bytes para reemplazar la conversión con ord.
xnor
@nwellnhof Ja, ¡acabo de encontrar lo mismo! Te acreditará de todos modos.
lirtosiast el
b"$>6;-/'?"[a&8and(~a&6or a>>4&6|1)]guarda otros cuatro bytes.
nwellnhof el
@nwellnhof Creo que una cadena de módulos es el camino a seguir aquí, pero si no, la suya ciertamente funcionaría.
lirtosiast el
9

JavaScript (Node.js) , 126 119 117 112 111 bytes

(a,b,c,d,e,f,g,h,i,j)=>[(g&h&i+(b+=a*4+b,e+=d*4+e)!=5?8:b)+c,(g&i?h+e-3?8:b:e)+f,(g?h<i?e:h>i*e?b:8:h*4+i*2)+j]

Pruébalo en línea!

-5 bytes gracias @tsh (y 2 solo) Así que lpuedo hacer más esfuerzo de lo que esperaba.

-2 bytes más usando la técnica de @ tsh!

-5 bytes gracias @Arnauld

-1 byte gracias @Neil

Entrada como una lista de 10 bits (como 10 argumentos), salida como una lista de 3 dígitos.

Shieru Asakoto
fuente
1
(!i|!d|e)-> i+l!=5; (d|e|!h)->h+l!=1
tsh
1
(g?h-i|h&!e?h?b:e:8:h*4+i*2)-> (g?h<i?e:h>i*e?b:8:h*4+i*2)guarda otro byte. (Lo comprobé esta vez ...)
Neil
8

C (gcc) , 138 129 bytes

f(w){int t=w/2&55,s=t%8,v=w/16,u=v/8;w=((s<6|t==39?u:8|u%2)*10+v%2+(s&5^5?v&6:t-23?8:u&6))*10+w%2+(s<5?s*2:s<6?v&6:s%t<7?u&6:8);}

Pruébalo en línea!

Primero extrae algunos bits en variables sy t, para que las ocho filas de la tabla de conversión puedan identificarse mediante:

1.  s < 4              u v w¹
2.  s = 4              u v 8¹
3.  s = 5              u 8 v
4.  s = 6              8 v u
5.  s = 7, t =  7      8 8 u
6.  s = 7, t = 23      8 u 8
7.  s = 7, t = 39      u 8 8
8.  s = 7, t = 55      8 8 8

¹ Can be computed with s*2

Luego se configura uy vcon divisiones (desplazamiento a la derecha), de modo que u, vy la entrada wcontiene los tres bits BCD inferiores en las posiciones 0-2. El resto es un poco aleatorio dependiendo de sy t. Dos trucos notables son:

s&5^5  // Rows 1, 2 and 4.
s%t<7  // Rows 1-5.

Un puerto de la solución Javascript de Shieru Asakoto tiene solo 124 bytes :

f(a,b,c,d,e,f,g,h,i,j){a=(((g&h&i+(b+=a*4+b,e+=d*4+e)!=5?8:b)+c)*10+(g&i?h+e-3?8:b:e)+f)*10+(g?h-i|h&!e?h?b:e:8:h*4+i*2)+j;}

Pruébalo en línea!

nwellnhof
fuente
Creo que se puede acortar a:f(b){int a=b/2%8,e=b&110,c=b/16,d=c/8;b=10*(10*(d%2|(6>a|78==e?d:8))+c%2+(3<a&a%2?e-46?8:d&6:c&6))+b%2+(4>a?b&6:a-5?a-6&&e-14?8:d&6:c&6)};
MCCCS
@MCCCS Su código también parece tener 138 bytes.
nwellnhof
5

Ruby , 153 ... 119117 bytes

->n{n+=n&896;a,b,c=n&1536,n&96,n&14;"%x"%n+=c<9?0:2036+[b/16-b-1918,r=a>>8,[r+126,a/16-26,a-1978,38][b/32]-a][c/2-5]}

Pruébalo en línea!

Cómo funciona:

->n{n+=n&896;

Este es el punto de partida: convierta a BCD desplazando 3 bits a la izquierda, lo que funciona para la mayoría de los patrones.

a,b,c=n&1536,n&96,n&14;

Obtenga los bits medios de cada mordisco (y un bit extra del tercer mordisco, pero enmascare el bit menos significativo).

"%x"%n+=c<9?0

Si el tercer dígito es menor que 10 (menor que 9 porque de todos modos nunca nos importó el LSB), estamos listos: esto es BCD simple, podemos generar el hexadecimal sin cambiar nada

:2036+[b/16-b-1918,r=a>>8,[r+126,a/16-26,a-1978,38][b/32]-a][c/2-5]}

De lo contrario, haz algo de magia negra cambiando los bits y agregando números mágicos hasta que obtengamos el resultado que queremos.

GB
fuente
5

Retina 0.8.2 , 191 181 bytes

(...)(...)
:$1,$2;
..(.),11(.);111
100$1,100$2;100
(10|(..)(.,)01)(.);111
100$3$2$4;100
(..)(.),(00.);111
100$2,1$3;0$1
(..)((.{5});110|(.);101)
100$3$4;$1
1
01
+`10
011
.0+(1*)
$.1

Pruébalo en línea! El enlace incluye casos de prueba. Editar: guardado 10 bytes al no rellenar dígitos a 4 bits, excepto cuando sea necesario. Explicación:

(...)(...)
:$1,$2;

Inserte separadores para que cada dígito se pueda convertir a decimal por separado. Esto maneja efectivamente los dos primeros casos en la tabla de conversión.

..(.),11(.);111
100$1,100$2;100

Maneje el último (octavo) caso en la tabla de conversión.

(10|(..)(.,)01)(.);111
100$3$2$4;100

Manejar los casos sexto y séptimo en la tabla de conversión.

(..)(.),(00.);111
100$2,1$3;0$1

Manejar el quinto caso en la tabla de conversión.

(..)((.{5});110|(.);101)
100$3$4;$1

Manejar los casos tercero y cuarto en la tabla de conversión.

1
01
+`10
011
.0+(1*)
$.1

Realizar conversión de binario a decimal.

Neil
fuente
5

Jalea , 51 48 40 39 bytes

&\‘f4;s3ɓạ4ḅ-œ?µ/Ḥ
“MY-€-Y¤©¡‘Dịs3Ḅç+ƭ/

Pruébalo en línea!

Algoritmo

Con la excepción de los índices de lista, todos los enteros en esta sección están escritos en binario.

Entrada dada αβγδεζηθικ, primero construimos las matrices [ηη,θι,δε], [αβ,δε,θι]y [γ,ζ,κ].

  1. Si ηη=00, los tres dígitos de salida son bajos (0000 a 0111)
  2. Si ηη=11 pero θι<11, exactamente un dígito de salida es alto (1000 o 1001)
  3. Si ηη=θι=11 pero δε<11, exactamente dos dígitos de salida son altos.
  4. Si ηη=θι=δε=11, los tres dígitos de salida son altos.

Si contamos el número de líderes 11's [ηη,θι,δε], cree una matriz de un número coincidente de 100's, concatenarlo con [αβ,δε,θι]y dividimos el resultado en submatrices de longitud tres, obtenemos los siguientes resultados en cada caso.

  1. [[αβ,δε,θι]]
  2. [[100,αβ,δε],[θι]]
  3. [[100,100,αβ],[δε,θι]]=[[100,100,αβ],[δε,11]]
  4. [[100,100,100],[αβ,δε,θι]]=[[100,100,100],[αβ,11,11]]

En el primer y último caso, solo tenemos que comprimir la primera matriz con [γ,ζ,κ], cediendo [αβγ,δεζ,θικ] en el primer caso y [100γ,100ζ,100κ] en el último.

Los dos casos restantes son similares, pero las matrices [100,αβ,δε] y [100,100,αβ] tiene que ser reordenado, de acuerdo con los valores de [θι] y posiblemente δε.

En el segundo caso, las seis permutaciones de [100,αβ,δε] son [100,αβ,δε], [100,δε,αβ], [αβ,100,δε], [αβ,δε,100], [δε,100,αβ], and [δε,αβ,100].

By computing 100θι, we map 00, 01, and 10 to four, three and two, selecting the permutations [αβ,δε,100], [αβ,100,δε], and [100,δε,αβ].

After zipping the result with [γ,ζ,κ], we get [αβγ,δεζ,100κ], [αβγ,100ζ,δεκ], or [100γ,δεζ,αβκ].

In the third case, the permutations (with duplicates) of [100,100,αβ] are [100,100,αβ], [100,αβ,100], [100,100,αβ], [100,αβ,100], [αβ,100,100] and [αβ,100,100].

By computing (100θι)(100δε)=δεθι=δε11, we map 00, 01, and 10 to three, four, and five modulo six, selecting the permutations [100,100,αβ], [100,αβ,100], and [αβ,100,100].

After zipping the result with [γ,ζ,κ], we get [100γ,100ζ,αβκ], [100γ,αβζ,100κ], or [αβγ,100ζ,100κ].

Code

“MY-€-Y¤©¡‘Dịs3Ḅç+ƭ/  Main link. Argument: A (array of 10 bits)

“MY-€-Y¤©¡‘           Array literal; yield [77, 89, 45, 12, 45, 89, 3, 6, 0].
           D          Decimal; yield
                      [[7,7], [8,9], [4,5], [1,2], [4,5], [8,9], [3], [6], [0]].
            ị         Retrieve the elements of A at those indices.
                      Indexing is 1-based and modular, so 1 is the first index, while
                      0 is the last.
             s3       Split the results 2D array of bits into chunks of length 3.
               Ḅ      Convert the 9 arrays of bits from binary to integer.
                ç+ƭ/  Reduce the resulting array (length 3) once by the helper link,
                      then by addition.


&\‘f4;s3ɓạ4ḅ-œ?µ/Ḥ    Helper link. Arguments: B, C (arrays of three integers each)

&\                    Cumulatively reduce B by bitwise AND.
  ‘                   Increment the results by 1.
   f4                 Filter; keep only integers equal to 4.
     ;                Concatenate the result with C.
      s3              Split the result into (one or two) chunks of length 3.
        ɓ      µ/     Reduce the array of chunks by the following chain.
         ạ4               Take the absolute difference of the integers in the right
                          chunk and the integer 4.
           ḅ-             Convert the resulting array from base -1 to integer, i.e.,
                          map [x] to n = x and [x, y] to n = y - x.
             œ?           Take the n-th permutation of the left chunk.
                 Ḥ    Unhalve; multiply the resulting integers by 2.
Dennis
fuente
2

Python 2, 157 bytes

lambda a,b,c,d,e,f,g,h,i,j:[c+[a*4+b*2,8][g*h*~(d*~e*i)],f+[d*4+e*2,8,a*4+b*2][g*i+(d<e)*g*i*h],j+[h*4+i*2,[8,[a*4+b*2,d*4+e*2][h<i]][h^i or(h&i-(d|e))]][g]]

Try it online!

TFeld
fuente
2

Clean, 238 ... 189 bytes

-2 bytes thanks to Neil

import StdEnv
$a b c d e f g h i j=100*(c+2*b+4*a)+10*(f+2*e+4*d)+j+2*i+4*h-2*(h*(99*b+198*a-394)+i*(9*e+18*d+h*(e+2*d-4+(b+2*a-4)*(1-10*e-100*d+110*e*d))-35)-4)*g+0^(e+d)*(2*b+4*a-8*i*h*g)

Try it online!

Takes a 'list' of 10 bits in the form of 10 arguments, using a direct formula to compute the result.

Οurous
fuente
In i*(9*e+19*d+i*...), that second i* looks unnecessary.
Neil
@Neil You're right, it is, thanks.
Οurous
1

Perl 5, 195 bytes

sub f{$n=shift;@p=((map{($n>>$_&3)*2}(8,5,1)),8);for(16390,28935,29005,227791,29108,225788,226803,228863){return 2*$n&256|$n&17|$p[$_>>4&3]<<8|$p[$_/4&3]<<4|$p[$_&3]if($_>>12&$n/2)==($_>>6&63);}}

Try it online

I know 195 bytes is far too much for this contest, but I had no idea how to further compress the Perl code. Suggestions?

Explanation of the code

In a more readable version, the code intention should become apparent:

sub dpd {
  my $n = shift;
  my $v=2*($n&128)|$n&17;
  my @p=((map{($n>>$_&3)*2}(8,5,1)),8);
  for (16390,28935,29005,227791,29108,225788,226803,228863) {
    return $v |$p[$_>>4&3]<<8|$p[$_>>2&3]<<4|$p[$_&3]
      if(($_>>12&$n/2)==($_>>6&63));
  }
}

In the rules for DPD encoding, each line is encoded into a 18 bit value, segmentation into (6,6,(2,2,2)) bits.

  • The first 6 bits are an appropriate bit mask for the bits 1 (=h) to 6 (=d) of the input (bit 4 = f is redundant, but it simplifies the evaluation code to have it included).
  • The next 6 bits are the value bits for this bit mask. The values are checked on all places where the bit mask has a 1 value.
  • The following 3*2 bits contain the indices for the array @p for the 3-bit sequences which are to spliced into bits 11-9, 7-5 and 3-1 of the result.
  • The array @p is constructed from bits 9-8, 6-5, 3-2 of the input, and the number 8 as fourth member
  • The bits at position 7,4 and 0 of the input are transferred directly into bits 8,4 and 0 of the result.

For example, the first number in the list, 16390, which is 100000000000110 as a bit field, carries the following information:

000100 : bit mask says: only consider bit 3 of the input
000000 : bit values say: bit 3 should be 0
00     : use '0ab' as higher bits of first digit
01     : use '0de' as higher bits of second digit
10     : use '0gh' as higher bits of third digit
rplantiko
fuente
1

05AB1E, 84 bytes

Port of KimOyhus' answer to 05AB1E.

•4’7þ2Ô€iΘEuĆΣk4Ѐ:ΘΛs‡CaΔʒì₁3¶rdiMß¡þи иø-˜)Â∍DY—WûQ@—Mā}Γ¤ÒÙ]p•44в2ôvÐyèP≠«}4ôC3.£

Try it online!

Rough explanation:

•yadayada•44в2ô   # encoded list of nand gates
v                 # for each gate
 ÐyèP≠            # compute the output of the gate
      «           # append it to the input
       }          # end of the loop
4ô                # split the list of bits in groups of 4
  C               # convert each from binary to decimal
   3.£            # keep the last 3 numbers
                  # implicit output
Grimmy
fuente
0

05AB1E, 104 103 101 bytes

•3γã•S£©4èUXтÌ‹XSPVY®2èDˆTQ*~i0®нëт}®1èY¯`*i0®нëY_Xт>Ê*i0¯`ëт]®3èY¯`_*X110Q~i0®нëXт›iYiтë0¯`ëX]®θJ4ôC

Definitely not the right language for this kind of challenge, but ah well..
Input as string, output as list of three digits.

Try it online or verify all test cases.

Explanation:

We have the following eight scenarios to consider:

     1st 2nd 3rd 4th 5th 6th                          1st digit    2nd digit    3rd digit
1.   ab  c   de  f   0gh i   →   0abc 0def 0ghi   →   '0'+1st 2nd  '0'+3rd 4th  5th     6th
2.   ab  c   de  f   100 i   →   0abc 0def 100i   →   '0'+1st 2nd  '0'+3rd 4th  5th     6th
3.   ab  c   gh  f   101 i   →   0abc 100f 0ghi   →   '0'+1st 2nd  '100'   4th  '0'+3rd 6th
4.   gh  c   de  f   110 i   →   100c 0def 0ghi   →   '100'   2nd  '0'+3rd 4th  '0'+1st 6th
5.   gh  c   00  f   111 i   →   100c 100f 0ghi   →   '100'   2nd  '100'   4th  '0'+1st 6th
6.   de  c   01  f   111 i   →   100c 0def 100i   →   '100'   2nd  '0'+1st 4th  '100'   6th
7.   ab  c   10  f   111 i   →   0abc 100f 100i   →   '0'+1st 2nd  '100'   4th  '100'   6th
8.   xx  c   11  f   111 i   →   100c 100f 100i   →   '100'   2nd  '100'   4th  '100'   6th

I first split the (implicit) input into chunks of size [2,1,2,1,3,1] and store that list in the register:

3γã•     # Push compressed integer 212131
     S    # Convert it to a list of digits
      £   # Split the (implicit) input in chunks of that size
       ©  # Store it in the register (without popping)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why •3γã• is 212131

Now we're first going to built the 0s and 1s for the first digit of the output. Scenarios 1,2,3,7 use '0'+1st+2nd; and scenarios 4,5,6,8 use '100'+2nd:

4è                  # Take the 5th item of the list
  U                 # Pop and store it in variable `X`
XтÌ‹                #  Check if `X` is below 102
                ~   # OR
   XSP              #  `X` is equal to 111
      VY            #  And store that result in variable `Y`
               *    #  and
        ®2è         #  Get the 3rd item from the list of the register
           Dˆ       #  Push it to the global array
             TQ     #  And check if it's equal to 10
i                   # If the combined check above is truthy (exactly 1):
 0                  #  Push 0 to the stack
 ®н                 #  Push the 1st item of the list to the stack
ë                   # Else:
 т                  #  Push 100 to the stack
}                   # Close the if-else
®1è                 # And push the 2nd item of the list to the stack

Then we're going to built the 0s and 1s for the second digit of the output. Scenarios 1,2,4 use '0'+3rd+4th; scenarios 3,5,7,8 use '100'+4th; and scenario 6 uses '0'+1st+4th:

Y                # Push `Y` (check if `X` equals 111)
   *             # and
 ¯`              # Push the item from the global array (3rd item of the list)
i                # If both checks above are truthy (exactly 1):
 0               #  Push 0 to the stack
 ®н              #  Push the 1st item of the list to the stack
ë                # Else:
 Y_              #  Push inverted `Y` (check if `X` does NOT equal 111)
       *         #  and
   Xт>Ê          #  Check if `X` (5th item of the list) does NOT equal 101
 i               #  If both checks above are truthy (exactly 1):
  0              #   Push 0 to the stack
  ¯`             #   Push the item from the global array (3rd item of the list)
 ë               #  Else:
  т              #   Push 100 to the stack
]                # Close both if-else cases
®3è              # And push the 4th item of the list to the stack

Then we're going to built the 0s and 1s for the third digit of the output. Scenarios 1,2 use 5th+6th; scenario 3 uses '0'+3rd+6th; scenarios 4,5 use '0'+1st+6th; and scenarios 6,7,8 use '100'+6th:

Y           #  Push `Y` (check if `X` equals 111)
    *       #  and
 ¯`_        #  Check if the item from the global array (3rd item of the list) is exactly 0
         ~  # OR
    X110Q   #  Check if `X` (5th item of the list) equals 110
i           # If the combined check above is truthy (exactly 1):
 0          #  Push 0 to the stack
 ®н         #  Push the 1st item of the list to the stack
ë           # Else:
 Xт›i       #  If `X` (5th item of the list) is larger than 100 (so 101/110/111):
     Yi     #   If `Y` (if `X` equals 111):
       т    #    Push 100 to the stack
      ë     #   Else:
       0    #    Push 0 to the stack
       ¯`   #    Push the item from the global array (3rd item of the list)
    ë       #  Else:
     X      #   Push `X` (5th item of the list) to the stack
]           # Close all if-else cases
®θ          # And push the last (6th) item of the list to the stack

Now we have all 0s and 1s on the stack, so we can convert it to the three output digits:

J     # Join the entire stack together
 4ô   # Split it into parts of size 4
   C  # Convert each part from binary to an integer (and output implicitly)
Kevin Cruijssen
fuente