Decodificar a sequência


41

Este é o meu primeiro desafio no ppcg!

Entrada

Uma sequência que consiste em dois caracteres ascii diferentes. Por exemplo

ABAABBAAAAAABBAAABAABBAABA

Desafio

A tarefa é decodificar essa sequência seguindo estas regras:

  1. Pule os dois primeiros caracteres
  2. Divida o restante da sequência em grupos de 8 caracteres
  3. Em cada grupo, substitua cada caractere por 0se esse caractere for igual ao primeiro caractere da sequência original e por 1outro
  4. Agora cada grupo representa um byte. Converter cada grupo em caractere a partir do código de bytes
  5. Concatene todos os caracteres

Exemplo

Vamos decodificar a string acima.

 AB  AABBAAAA  AABBAAAB  AABBAABA
 ^^     ^         ^         ^
 |      |         |         |
 |      \---------|---------/
 |                |
Skip      Convert to binary

Observe que esse Aé o primeiro caractere da string original e Bo segundo. Portanto, substitua cada um Apor 0e cada um Bpor 1. Agora obtemos:

00110000  00110001  00110010

que está [0x30, 0x31, 0x32]em binário. Esses valores representam caracteres ["0", "1", "2"]respectivamente, portanto a saída final deve ser 012.

Pontuação

Isso é, é claro, , o que significa tornar seu código o mais curto possível. A pontuação é medida em bytes.

Restrições e formato IO

Aplicam-se regras padrão. Aqui estão algumas regras adicionais:

  • Você pode assumir uma entrada válida
    • A sequência de entrada consiste em exatamente dois caracteres diferentes
    • Os dois primeiros caracteres são diferentes
    • O comprimento mínimo da sequência de entrada é de 2 caracteres
    • O comprimento sempre dará 2 módulos 8
  • Você pode assumir que a string sempre consistirá apenas em caracteres ASCII imprimíveis
    • Tanto na entrada quanto na string decodificada
  • Os espaços em branco à esquerda e à direita são permitidos na saída (tudo o que corresponde /\s*/)

5
Tenho que dizer cara, para um primeiro desafio, este é um dos desafios melhor formatados que eu já vi. Como fyi, a área restrita da comunidade é um ótimo local para feedback antes de postar, para que você não seja repetidamente bombardeado por uma regra que não conhecia.
Magic Octopus Urn

@MagicOctopusUrn. Obrigado! Não sabia sobre sandbox, vou postar lá na próxima vez :)

2
Eu o uso principalmente para que as pessoas possam me chamar de perguntas duplicadas, muito simples de seguir regras, um pouco difícil de saber sobre bobagens sem memorizar a meta :). Eu também recomendo conferir as salas de bate-papo, temos bate-papos para quase todos os idiomas que você espera aprender e as perguntas são incentivadas.
Magic Octopus Urn

1
Grande primeiro desafio! Mais alguns casos de teste seriam legais.
Lynn

Muito bom primeiro desafio. Diverti-me a brincar com este.
ElPedro

Respostas:



8

Stax , 15 11 bytes

ó║¥U⌂½íèäöñ

Execute e depure-o em staxlang.xyz!

Abordagem rápida e suja. Trabalhando para melhorá-lo. Melhorou!

Descompactado (13 bytes) e explicação

2:/8/{{[Im:bm
2:/              Split at index 2. Push head, then tail.
   8/            Split into length-8 segments.
     {      m    Map block over each segment:
      {  m         Map block over each character:
       [             Copy first two elements (below) in-place.
        I            Index of character in first two characters.
          :b       Convert from binary.
                 Implicit print as string.

Ahhhh ... eu sabia que isso iria nos vencer.
Magic Octopus Urn

6

JavaScript (Node.js) , 67 bytes

s=>s.replace(/./g,x=(c,i)=>(x=x*2|c==s[1],Buffer(i<3|i&7^1?0:[x])))

Experimente online!

Quão?

Usamos duas sintaxes diferentes do Bufferconstrutor:

  • Buffer([n])gera um buffer que contém o único byte n e é coagido ao caractere ASCII correspondente. Apenas os 8 bits menos significativos de n são considerados.
  • Buffer(n)gera um buffer de n bytes. Portanto, Buffer(0)gera um buffer vazio, que é coagido a uma cadeia vazia.

Nota: Ambos foram descontinuados nas versões recentes do Nó. Buffer.from([n])e Buffer.alloc(n)deve ser usado em seu lugar.

Comentado

s =>                   // given the input string s
  s.replace(/./g, x =  // initialize x to a non-numeric value (will be coerced to 0)
    (c, i) => (        // for each character c at position i in s:
      x = x * 2 |      //   shift x to the left
          c == s[1],   //   and append the new bit, based on the comparison of c with s[1]
      Buffer(          //   invoke the constructor of Buffer (see above):
        i < 3 |        //     if i is less than 3
        i & 7 ^ 1 ?    //     or i is not congruent to 1 modulo 8:
          0            //       replace c with an empty string
        :              //     else:
          [x]          //       replace c with the ASCII char. whose code is the LSB of x
      )                //   end of Buffer constructor
  ))                   // end of replace(); return the new string

6

bash, 59 58 52 bytes

tr -t "$1" 01 <<<$1|cut -c3-|fold -8|sed 'i2i
aP'|dc

Experimente online!

Agradecimentos ao vacas charlatão por economizar 6 bytes.

Esse desafio funciona muito bem com uma série de coreutils (e dcpara fazer a conversão e a saída no final). Primeiro, usamos

tr -t "$1" 01 <<<$1

transliterar os dois caracteres na entrada para zeros e uns. O -tsinalizador trunca o primeiro argumento para o comprimento do segundo, então isso reduz a transliteração dos dois primeiros caracteres da entrada para 0e 1, que é o que queremos. Então,

cut -c3-

remove os dois primeiros caracteres e

fold -8

produz 8 dos caracteres por linha. Por fim, o sedcomando transforma cada linha em um dctrecho que lê o número como binário e gera esse byte.


É sempre bom ver uma resposta bash :) Você pode usar sed para simplificar os cálculos de CC convertendo cada linha em código CC que imprime cada caractere e depois avaliando-o em dc tio.run/##S0oszvj/… ( espaço depois cut -cpode ser removida)
Kritixi Lithos

6

Código de máquina Z80 em um CPC da Amstrad, 32 31 30 bytes

000001  0000  (9000)        ORG &9000
000002  9000  EB            EX DE, HL
000003  9001  46            LD B, (HL)
000004  9002  23            INC HL
000005  9003  5E            LD E, (HL)
000006  9004  23            INC HL
000007  9005  56            LD D, (HL)
000009  9006  1A            LD A, (DE)
000010  9007  05            DEC B
000011  9008  13            INC DE
000012  9009  4F            LD C, A
000014  900A                Light
000015  900A  26 01         LD H, &01
000016  900C                Last
000017  900C  13            INC DE
000018  900D  05            DEC B
000019  900E  C8            RET Z
000021  900F                Loop
000022  900F  1A            LD A, (DE)
000023  9010  B9            CP C
000024  9011  28 01         JR Z, Lable
000025  9013  37            SCF
000026  9014                Lable
000027  9014  ED 6A         ADC HL, HL
000028  9016  30 F4         JR NC, Last
000029  9018  7D            LD A, L
000030  9019  CD 5A BB      CALL &BB5A
000032  901C  18 EC         JR Light

O código leva a instrução substituir cada caractere 0se esse caractere for o mesmo que o primeiro caractere da string original e por 1outro literalmente e nunca se incomodará em verificar se um caractere corresponde ao segundo caractere na string de entrada. Apenas verifica o mesmo que o primeiro caractere e o diferente do primeiro caractere.

Eu corri para fora de registros (o Z80 tem apenas 7 registros de 8 bits facilmente utilizáveis, instruções a necessidade de descanso mais longos) por isso eu coloquei &01em H, juntamente com o uso Lpara construir o caráter ASCII (Eu só percebi que é desnecessário para inicializar L, salvando um byte ) Quando Htransborda para o sinalizador Carry, o caractere Lestá pronto para a saída. Felizmente, há um 16-bit ADC( Ad d with C arry) que faz o trabalho de uma instrução de turno à esquerda.

(DE)só pode ser lido, Aembora (HL)possa ser lido em qualquer registrador de 8 bits; portanto, era um compromisso qual deles usar. Eu não poderia comparar (DE)com Cdiretamente, então eu tive que carregar um em Aprimeiro lugar. Os rótulos são apenas palavras aleatórias que começam com L(um requisito do montador).

  • A o acumulador - o único registro que pode fazer comparações
  • Bo contador de registo para a instrução DJNZ: D ecrement ( B) e J ump se N em Z ero . Reorganizando o código, consegui fazer o trabalho DJNZcom menos um byte
  • C o primeiro caractere na sequência de entrada
  • D, Ecomo DEo endereço do caractere de entrada atual
  • H o gatilho de transporte (a cada 8º loop)
  • L o caractere de saída que está sendo construído

insira a descrição da imagem aqui


6

05AB1E , 10 bytes

¦¦Sk8ôJCçJ

Experimente online!

-3 graças a emigna.


Ù             # Unique letters, in order they appear.
 v            # For each...
  yN:         # Push letter and index, replace in input.
     }        # End loop.
      ¦¦      # Remove first x2.
        8ô    # Split into eighths.
          C   # Convert to integer.
           ç  # Convert to char.
            J # Join together entire result.

1
Você pode usar em 01‡vez do loop. Edição: ou ainda melhor:¦¦Sk8ôJCçJ
Emigna 23/04


5

J, 17 13 bytes

u:_8#.\2}.1{=

-4 graças a FrownyFrog

Versão antiga:

u:_8#.\2&({.i.}.)

Explicação:

u:_8#.\2}.1{=
            =  | Self classify, for each unique element x of y, compute x = y, element-wise
          1{   | Second row
       2}.     | Drop 2
  _8#.\        | Convert non-intersecting subarrays of length 8 from binary
u:             | Convert to characters

Exemplos:

   = 'ABAABBAAAAAABBAAABAABBAABA'
1 0 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 0 1 1 0 0 1 1 0 1
0 1 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0

   2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0

   _8#.\2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
48 49 50

   u:_8#.\2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
012

1
2}.1{=para salvar 4 bytes.
precisa saber é o seguinte

Oh meu, amarrado ... Não consigo encontrar outro byte.
Urna Mágica do Polvo

1
@MagicOctopusUrn é realmente um trecho, ele deve ter um [:no início :)
FrownyFrog


5

R , 71 bytes

function(s)intToUtf8(2^(7:0)%*%matrix((y=utf8ToInt(s))[-1:-2]==y[2],8))

Experimente online!

Surpreendentemente golfe!

Primeiro, converte a string em pontos de código ascii com utf8ToInt, salvando-a como y. A remoção dos dois primeiros caracteres com indexação negativa é mais curta que a utilização tail.

A matriz y[-1:-2]==y[2]é equivalente aos bits quando %*%(multiplicação de matrizes) é aplicada, mas primeiro remodelamos essa matriz em um matrixcom nrow=8, convertendo de uma matriz linear em agrupamentos de bytes. Felizmente, podemos converter para os pontos de código ascii usando a multiplicação de matrizes com os poderes apropriados de 2 e 2^(7:0), em seguida, convertemos os pontos de código novamente em uma string com intToUtf8.



4

PHP, 73 71 bytes

while($s=substr($argn,-6+$i+=8,8))echo~chr(bindec(strtr($s,$argn,10)));

Execute como pipe -nRou experimente on-line .

golfe:

  • inicie o índice em -6 e pré-incremento em8
  • exploração que strtrignora caracteres excessivos no parâmetro mais longosubstr necessário)
  • traduzindo para 10 e depois inverter não precisa de aspas -> -1 byte
  • caractere invertido em vez de código ascii -> ~serve como limite da palavra -> -1 byte.

3
Pelo menos você deve combinar brainfuck:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph

2
@Christoph Eu gosto de como o Brainfuck de repente é um padrão para um tamanho razoável de resposta.
Nit

4

Pitão, 20 9 bytes

CittxLQQ2

Economizou 11 bytes graças a FryAmTheEggman.

Experimente aqui

Explicação

CittxLQQ2
    xLQQ    Find the index of each character in the string.
  tt        Exclude the first 2.
 i      2   Convert from binary.
C           Get the characters.

@FryAmTheEggman Thanks. Evidentemente, ainda tenho muito a aprender sobre Pyth.
Mnemônico

Haha, eu também! É uma linguagem de golfe muito complexa. Eu espero que você continue golfe nele :)
FryAmTheEggman

3

Ruby , 82 79 bytes

->s{s[2..-1].tr(s[0,2],'01').chars.each_slice(8).map{|s|s.join.to_i(2).chr}*''}

Experimente online!


1
Bem-vindo ao PPCG! Eu não vi que já havia uma resposta em Ruby antes de publicar a minha, mas alguns truques típicos de golfe também se aplicam à sua abordagem - por exemplo, o último .joinpode ser substituído por *''e s[0..1]por s[0,2].
precisa

3

Japonês, 11 bytes

¤£bXÃò8 ®Íd

Tente


Explicação

¤               :Slice from the 3rd character
 £  Ã           :Map over each X
  bX            :  Get the first 0-based index of X in the input
     ò8         :Split to an array of strings of length 8
        ®       :Map
         Í      :  Convert from base-2 string to base-10 integer
          d     :  Get the character at that codepoint

Uso muito inteligente do s2atalho, legal.
Nit

3

Precisão múltipla PHP + GNU, 63 61

<?=gmp_export(gmp_init(substr(strtr($argn,$argn,"01"),2),2));

infelizmente, a extensão GMP não é ativada por padrão (mas é enviada).

Execute assim:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=economiza 2 bytes e possivelmente o dia. ;-)
Titus

@ Titus sim, mas infelizmente não funciona -R(tentei).
Christoph

1
tente em -Fvez disso
Titus


3

Java 8, 143 142 141 bytes

s->{char i=47;for(;++i<50;)s=s.replace(s.charAt(i%2),i);for(i=2;i<s.length();)System.out.print((char)Long.parseLong(s.substring(i,i+=8),2));}

-1 byte graças a @ OlivierGrégoire .

Experimente online.

Explicação:

s->{                            // Method with String parameter and no return-type
  char i=47;                    //  Index character, starting at 47
  for(;++i<50;)                 //  Loop 2 times
    s.replace(s.charAt(i%2),i)  //   Replace first characters to 0, second characters to 1
  for(i=2;i<s.length();)        //  Loop `i` from 2 upwards over the String-length
    System.out.print(           //   Print:
     (char)                     //    As character:
      Long.parseLong(           //     Convert Binary-String to number
       s.substring(i,i+=8)      //      The substring in range [i,i+8),
      ,2));}



2

APL + WIN, 30 bytes

Origem do índice 0. Solicita a entrada da sequência

⎕av[2⊥¨(+\0=8|⍳⍴b)⊂b←2↓s≠↑s←⎕]

Explicação:

s≠↑s←⎕ prompts for string and creates binary vector not equal to first character

b←2↓s drops first two elements of binary

(+\0=8|⍳⍴b)⊂ splits binary into groups of 8

2⊥¨ converts each group to decimal

⎕av[...] displays decoded characters

Presumo que o Quad-AV esteja alinhado com o ASCII para APL + WIN?
Zachary

@ Zacharý Sim para os primeiros 128 caracteres. Os caracteres APL especiais substituem alguns dos caracteres no conjunto de caracteres ASCII estendido.
Graham

2

Vermelho , 110 bytes

func[s][t: 0 i: 128 foreach c next next s[if c = s/2[t: t + i]i: i / 2 if i = 0[prin to-char t t: 0 i: 128]]] 

Experimente online!

Explicação:

Uma solução simples e direta, sem recursos internos.

f: func [s] [                      ; s is the argument (string)
    t: 0                           ; total - initially 0
    i: 128                         ; powers of 2, initially 0
    b: s/2                         ; b is the second charachter
    foreach c next next s [        ; for each char in the input string after the 2nd one
        if c = b [t: t + i]        ; if it's equal to b than add the power of 2 to t
        i: i / 2                   ; previous power of 2
        if i = 0 [                 ; if it's 0 
            prin to-char t         ; convert t to character and print it
            t: 0                   ; set t to 0
            i: 128                 ; i to 128
        ]
    ]
] 

2

Planilhas Google, 123 bytes

=ArrayFormula(Join("",IfError(Char(Bin2Dec(Substitute(Substitute(Mid(A1,3+8*(Row(A:A)-1),8),Left(A1),0),Mid(A1,2,1),1))),""

A entrada está na célula A1 . O Google adicionará automaticamente))) ao final da fórmula.

Explicação:

  • Mid(A1,3+8*(Row(A:A)-1),8) pega pedaços de caracteres 8 de cada vez, começando com o terceiro.
  • Substitute(Mid(~),Left(A1),0) substitui cada instância do primeiro caractere por 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) substitui o segundo caractere por 1.
  • Char(Bin2Dec(Substitute(~))) converte o pedaço em decimal e depois em ASCII.
  • IfError(Char(~,""))corrige todos os erros que resultam do fato de Row(A:A)retornar muito mais valores do que nós, Bin2Decfornecendo muitos valores zero e Charerros no zero.
  • ArrayFormula(Join("",IfError(~)))une todos os Charresultados e ArrayFormulaé o que torna o Row(A:A)retorno uma matriz de valores em vez de apenas o primeiro valor.




2

Python 2 , 88 bytes

i=input()
f=''.join('10'[x==i[0]]for x in i[2:])
while f:print chr(int(f[:8],2));f=f[8:]

Experimente online!

Não é o mais curto - apenas uma maneira alternativa.

A versão a seguir imprime a saída em uma linha por 98 bytes, embora as regras determinem que espaço em branco à direita é permitido:

i=input();f=''.join('10'[x==i[0]]for x in i[2:]);o=""
while f:o+=chr(int(f[:8],2));f=f[8:]
print o

Experimente online!


A saída final deve estar em uma linha, não em três.
idrougge

No OP: "Espaços em branco à esquerda e à direita são permitidos na saída (tudo o que corresponde a / \ s * /)". Nova linha corresponde /\s*/.
ElPedro

1
Desculpe, eu não sou suficientemente versado na notação regex. : /
idrougge

Nem eu, mas eu Googled-lo só para ter certeza ;-)
ElPedro




1

Haskell , 124 105 93 bytes

f(x:_:y)=fromEnum.(/=x)<$>y
g[]=[]
g s=(toEnum.sum.zipWith((*).(2^))[7,6..0])s:g(drop 8s)
g.f

Experimente online!

fconverte a string em uma lista de bits comparando cada caractere com o primeiro, transformando Bools em zeros e uns com fromEnum. gdivide esta lista em grupos de 8, converte-os em decimal e assume o valor do número resultante como um Enum, que Charé uma instância de.

Alterar:

  • -19 bytes graças a @Laikoni (removendo a importação, incorporando map à função)
  • -12 bytes inspirados na resposta de @ Lynn (livrar-se de takefechar com uma lista mais curta)

2
Você pode usar em toEnumvez de chre soltar a importação. Também mappode ser incluído no g. O espaço entre eles 8 spode ser removido.
Laikoni

1

Quarto (gforth) , 83 bytes

: f over c@ 0 rot 2 do 2* over i 4 pick + c@ <> - i 8 mod 1 = if emit 0 then loop ;

Experimente online!

A entrada é uma saída padrão de string (endereço e comprimento) impressa em stdout

Explicação

over c@          \ get the value of the first character in the string
0 rot            \ add a starting "byte" value of 0 and put the length on top of the stack
2 do             \ start a loop from 2 to length-1
   2*            \ multiply the current byte value by 2 (shift "bits" left one)
   over          \ copy the reference char to the top of the stack
   i 4 pick +    \ add the index and the starting address to get address of the current char
   c@ <>         \ get the char at the address and check if not equal to the reference char
   -             \ subtract the value from our bit count, -1 is default "true" value in forth
   i 8 mod 1 =   \ check if we are at the last bit in a byte
   if            \ if we are
      emit 0     \ print the character and start our new byte at 0
   then          \ and end the if statement
loop             \ end the loop
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.