Décoder la chaîne


41

Ceci est mon premier défi sur ppcg!

Contribution

Une chaîne composée de deux caractères ASCII différents. Par exemple

ABAABBAAAAAABBAAABAABBAABA

Défi

La tâche consiste à décoder cette chaîne en suivant ces règles:

  1. Passer les deux premiers personnages
  2. Diviser le reste de la chaîne en groupes de 8 caractères
  3. Dans chaque groupe, remplacez chaque caractère par 0si ce caractère est identique au premier caractère de la chaîne d'origine, 1sinon par
  4. Maintenant, chaque groupe représente un octet. Convertir chaque groupe en caractère à partir du code de caractère octet
  5. Concaténer tous les personnages

Exemple

Décodons la chaîne ci-dessus.

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

Notez que Ac'est le premier caractère de la chaîne d'origine et Ble second. Par conséquent, remplacez chaque Aavec 0et chaque Bavec 1. Maintenant nous obtenons:

00110000  00110001  00110010

qui est [0x30, 0x31, 0x32]en binaire. Ces valeurs représentent les caractères ["0", "1", "2"]respectivement, donc le résultat final devrait être 012.

Notation

Il s’agit bien sûr de , ce qui signifie que votre code doit être aussi court que possible. Le score est mesuré en octets.

Contraintes et format IO

Les règles standard s'appliquent. Voici quelques règles supplémentaires:

  • Vous pouvez supposer une entrée valide
    • La chaîne d'entrée consiste en exactement deux caractères différents
    • Les deux premiers personnages sont différents
    • La longueur minimale de la chaîne d'entrée est de 2 caractères
    • La longueur donnera toujours 2 modulo 8
  • Vous pouvez supposer que la chaîne sera toujours composée uniquement de caractères ASCII imprimables.
    • À la fois dans l'entrée et dans la chaîne décodée
  • Les espaces de début et de fin sont autorisés dans la sortie (tout ce qui correspond /\s*/)

5
Je dois dire mec, pour un premier défi, c'est l'un des défis les mieux formatés que j'ai jamais vus. En tant que fyi, le sandbox de la communauté est un endroit idéal pour commenter avant de poster afin d'éviter de vous faire bombarder au hasard pour une règle que vous ne connaissiez pas.
Magic Octopus Urn

@MagicOctopusUrn. Merci! Je ne connaissais pas le bac à sable, j'y

2
Je l'utilise surtout pour que les gens puissent m'appeler sur des questions dupliquées, très simples à suivre les règles, plutôt difficiles à connaître sur les dupes sans mémoriser les méta :). Je recommanderais également de consulter les salles de discussion. Nous avons des discussions dans presque toutes les langues que vous pourriez espérer apprendre et les questions sont les bienvenues.
Magic Octopus Urn

1
Grand premier défi! Quelques autres cas de test seraient bien.
Lynn

Vraiment sympa premier défi. J'ai eu du plaisir à jouer avec celui-ci.
ElPedro

Réponses:



8

Stax , 15 à 11 octets

ó║¥U⌂½íèäöñ

Exécutez-le et déboguez-le sur staxlang.xyz!

Approche rapide 'n' dirty. Travailler à l'améliorer. Je l'ai amélioré!

Décompressé (13 octets) et explication

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 ... Je savais que cela nous battrait.
Urne magique Octopus

6

JavaScript (Node.js) , 67 octets

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

Essayez-le en ligne!

Comment?

Nous utilisons deux syntaxes différentes du Bufferconstructeur:

  • Buffer([n])génère un tampon contenant le seul octet n et est contraint au caractère ASCII correspondant. Seuls les 8 bits les moins significatifs de n sont pris en compte.
  • Buffer(n)génère un tampon de n octets. Par conséquent, Buffer(0)génère un tampon vide, qui est contraint à une chaîne vide.

Remarque: ils sont tous deux obsolètes dans les versions récentes des nœuds. Buffer.from([n])et Buffer.alloc(n)devrait être utilisé à la place.

Commenté

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 octets

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

Essayez-le en ligne!

Merci à Cocks Quack pour la sauvegarde de 6 octets.

Ce défi fonctionne remarquablement bien avec une série de coreutils (et dcd'effectuer la conversion et la sortie à la fin). Tout d'abord, nous utilisons

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

pour translittérer les deux caractères de l’entrée en zéros et en uns. Le -tdrapeau tronque le premier argument à la longueur du second, ce qui revient à translittérer les deux premiers caractères de l’entrée to 0et 1, c’est ce que nous souhaitons. Ensuite,

cut -c3-

supprime les deux premiers caractères, et

fold -8

affiche 8 caractères par ligne. Enfin, la sedcommande transforme chaque ligne en un dcextrait qui lit le nombre sous forme binaire et génère cet octet.


Il est toujours agréable de voir une réponse bash :) Vous pouvez utiliser sed pour simplifier les calculs en courant continu en convertissant chaque ligne de code cc qui imprime chaque personnage et ensuite il eval'ing en courant continu tio.run/##S0oszvj/... (et l’espace après cut -cpeut être supprimé)
Kritixi Lithos

6

Code machine Z80 sur un Amstrad CPC, 32 31 30 octets

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

Le code prend l'instruction de remplacer chaque caractère par 0si ce caractère est identique au premier caractère de la chaîne d'origine, 1sinon avec littéralement et sans se soucier de vérifier qu'un caractère correspond au deuxième caractère de la chaîne d'entrée. Il vérifie simplement que le caractère est identique au premier caractère et différent du premier.

Je courus des registres (le Z80 ne dispose de 7 facilement utilisables registres 8 bits, le besoin de repos plus longues instructions) donc je mets &01en H, avec l' aide Lde construire le caractère ASCII (je viens de réaliser qu'il est inutile d'initialiser L, sauver un octet ). En cas de Hdébordement dans le drapeau Carry, le caractère Lest prêt à être sorti. Heureusement, il existe un 16 bits ADC( Ad d avec C arry) qui remplit le rôle d'instruction de décalage à gauche.

(DE)ne peut être lu Aque bien que (HL)peut être lu dans n’importe quel registre de 8 bits, c’était donc un compromis que l’on utilisait. Je ne pouvais pas comparer (DE)avec Cdirectement, donc je devais en charger un en Apremier. Les étiquettes ne sont que des mots aléatoires qui commencent par L(une exigence de l’assembleur).

  • A l'accumulateur - le seul registre qui peut faire des comparaisons
  • Ble compteur enregistre pour l'instruction DJNZ: D ecrement ( B) et J ump si N sur Z ero . En réarrangeant le code, j'ai pu faire le travail DJNZavec un octet de moins.
  • C le premier caractère de la chaîne d'entrée
  • D, Ecomme DEadresse du caractère saisi
  • H le déclencheur de retenue (chaque 8ème boucle)
  • L le caractère de sortie en cours de construction

entrez la description de l'image ici


6

05AB1E , 10 octets

¦¦Sk8ôJCçJ

Essayez-le en ligne!

-3 grâce à 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
Vous pouvez utiliser à la 01‡place de la boucle. EDIT: ou même mieux:¦¦Sk8ôJCçJ
Emigna le


5

J, 17 13 octets

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

-4 grâce à FrownyFrog

Ancienne version:

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

Explication:

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

Exemples:

   = '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{=économiser 4 octets.
FrownyFrog

Oh mon Dieu, attaché ... Je ne peux pas trouver un autre octet.
Urne magique Octopus

1
@MagicOctopusUrn c'est en fait un extrait, il devrait en avoir un [:au début :)
FrownyFrog


5

R , 71 octets

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

Essayez-le en ligne!

Étonnamment golfy!

D'abord, convertit la chaîne en points de code ascii avec utf8ToInt, en l'enregistrant sous y. Supprimer les deux premiers caractères avec indexation négative est plus court que d’utilisertail .

Le tableau y[-1:-2]==y[2]est équivalent aux bits lorsque %*%(multiplication de matrice) est appliqué, mais nous reformulons d'abord ce tableau en un matrixavec nrow=8, en convertissant un tableau linéaire en groupements d'octets. Heureusement, nous pouvons ensuite convertir les points de code ascii en utilisant la multiplication de matrice avec les puissances appropriées de 2, 2^(7:0)puis nous reconvertissons les points de code en chaîne avec intToUtf8.



4

PHP, 73 71 octets

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

Exécuter en pipe -nRou essayer en ligne .

golfs:

  • commencer index à -6et pré-incrémenté par8
  • exploit qui strtrignore les caractères excessifs dans le paramètre long (pas substrnécessaire)
  • traduire 10, puis inverser, ne nécessite pas de guillemets -> -1 octet
  • inverser un caractère à la place d'un code ascii -> ~sert de limite de mot -> -1 octet.

3
Au moins, vous devriez être à la hauteur:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph le

2
@Christoph J'aime le fait que Brainfuck soit soudainement un standard pour une longueur de réponse raisonnable.
Nit

4

Pyth, 20 9 octets

CittxLQQ2

11 octets sauvés grâce à FryAmTheEggman.

Essayez-le ici

Explication

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 Merci. De toute évidence, j'ai encore beaucoup à apprendre sur Pyth.
Mnémonique

Haha, moi aussi! C'est une langue de golf très complexe. J'espère que vous continuerez à jouer au golf :)
FryAmTheEggman

3

Ruby , 82 79 octets

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

Essayez-le en ligne!


1
Bienvenue chez PPCG! Je n'avais pas vu qu'il y avait déjà une réponse dans Ruby avant d'avoir posté la mienne, mais quelques astuces de golf typiques s'appliquent également à votre approche - par exemple, la dernière .joinpeut être remplacée par *'', et s[0..1]par s[0,2].
Kirill L.

3

Japt, 11 octets

¤£bXÃò8 ®Íd

L'essayer


Explication

¤               :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

Utilisation très intelligente du s2raccourci, gentil.
Nit

3

Multiple + Précision PHP + GNU, 63 61

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

Malheureusement, l’extension GMP n’est pas activée par défaut (mais livrée).

Courez comme ça:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=enregistre 2 octets et éventuellement le jour. ;-)
Titus le

@ Titus ouais mais malheureusement ça ne marche pas avec -R(j'ai essayé).
Christoph

1
essayer -F place
Titus


3

Java 8, 143 142 141 octets

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 octet grâce à @ OlivierGrégoire .

Essayez-le en ligne.

Explication:

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 octets

Origine de l'index 0. Invites pour la saisie d'une chaîne

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

Explication:

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

Je suppose que Quad-AV est en ligne avec ASCII pour APL + WIN?
Zacharý

@ Zacharý Oui pour les 128 premiers caractères. Les caractères spéciaux APL remplacent certains des caractères du jeu de caractères ASCII étendu.
Graham

2

Rouge , 110 octets

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]]] 

Essayez-le en ligne!

Explication:

Une solution simple et directe, pas intégrée.

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

Google Sheets, 123 octets

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

L'entrée est dans la cellule A1. Google ajoutera automatiquement )))à la fin de la formule.

Explication:

  • Mid(A1,3+8*(Row(A:A)-1),8) saisit des morceaux de caractères 8 à la fois, en commençant par le troisième.
  • Substitute(Mid(~),Left(A1),0) remplace chaque instance du premier caractère par 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) remplace le deuxième caractère par 1.
  • Char(Bin2Dec(Substitute(~))) convertit le bloc en décimal, puis en ASCII.
  • IfError(Char(~,""))corrige toutes les erreurs qui résultent du fait que Row(A:A)renvoie beaucoup plus de valeurs que nous, ce Bin2Decqui nous donne beaucoup de valeurs nulles et des Charerreurs sur zéro.
  • ArrayFormula(Join("",IfError(~)))réunit tous les Charrésultats et ArrayFormulafait en sorte que le Row(A:A)retour d'un tableau de valeurs au lieu de la première valeur.




2

Python 2 , 88 octets

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

Essayez-le en ligne!

Pas le plus court - juste un moyen alternatif.

La version suivante imprime la sortie sur une ligne pour 98 octets, bien que les règles stipulent que les espaces de fin sont autorisés:

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

Essayez-le en ligne!


La sortie finale devrait être sur une ligne, pas trois.
Idrougge

De l'OP: "Les espaces de début et de fin sont autorisés dans la sortie (tout ce qui correspond à / \ s * /)". Newline matches /\s*/.
ElPedro

1
Désolé, je ne suis pas assez versé dans la notation regex. : /
idrougge

Je ne le suis pas non plus, mais je l'ai googlé pour en être sûr ;-)
ElPedro




1

Haskell , 124 105 93 octets

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

Essayez-le en ligne!

fconvertit la chaîne en une liste de bits en comparant chaque caractère au premier, en transformant le Bools en zéros et en uns avec fromEnum. gdivise cette liste en groupes de 8, les convertit en décimales et prend la valeur du nombre obtenu en tant que Enum, ce quiChar est une instance de.

Changements:

  • -19 octets grâce à @Laikoni (suppression de l'importation, intégration map dans la fonction)
  • -12 octets inspirés par la réponse de @ Lynn (se débarrasser de take en zippant avec une liste plus courte)

2
Vous pouvez utiliser et toEnumremplacer chrl'importation. Aussi le mappeut être inclus dans g. L'espace entre 8 speut être supprimé.
Laikoni

1

Forth (gforth) , 83 octets

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

Essayez-le en ligne!

L'entrée est une chaîne Forth standard (adresse et longueur), la sortie est imprimée sur stdout

Explication

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.