Fends-moi en deux

15

Vous recevrez un numéro x, où 0 <= x <= 2^32 - 1.

Vous devez sortir une liste de nombres en décimal, après une division récursive au format binaire.

Exemples:

Exemple 1:

255 -> 255 15 15 3 3 3 3 1 1 1 1 1 1 1 1

La liste actuelle est juste 255.

La représentation binaire de 255is 1111 1111. En le divisant, nous obtenons 1111et 1111, qui sont en décimal 15et 15.

Nous les ajoutons à la liste, donc nous aurons 255 15 15.

Maintenant, les nombres 15et 15serviront d'entrées et ces nombres doivent être divisés.

Le faire à nouveau, nous obtenons ( 3 3des deux 15s): 255 15 15 3 3 3 3.

Poursuivant la logique, la liste finale sera 255 15 15 3 3 3 3 1 1 1 1 1 1 1 1. Et comme 1il ne peut plus être divisé, la sortie s'arrête.

Exemple 2:

225 -> 225 14 1 3 2 1 1 1 0

La liste de départ est 225.

La représentation binaire de 225is 1110 0001. En le divisant, nous obtenons 1110et 0001, qui sont en décimal 14et 1.

En les ajoutant à la liste, nous obtenons 225 14 1.

Maintenant, les nombres 14et 1serviront d'entrées et ces nombres doivent être divisés.

Puisqu'il 1n'y a pas de division, la sortie le sera 225 14 1 3 2.

Exemple 3:

32 -> 32 4 0 1 0

Conditions :

  1. Si le nombre de chiffres binaires est impair, le premier nombre aura un chiffre binaire de moins que le suivant. Exemple, 20 (10100)sera divisé en tant que 10et 100, la sortie décimale étant 2et 4.
  2. Les règles standard des échappatoires s'appliquent.
  3. 0s et 1s ne se propagent plus.
  4. Un programme qui plante pour essayer d'afficher trop de nombres est une condition de sortie valide.
ctrl-shift-esc
la source
Juste une suggestion, mais qu'en est-il d'avoir les chiffres binaires remplis de 0s lorsque la longueur est impaire?
caird coinheringaahing
1
@ Satan'sSon Si vous vous placez devant, cela équivaut à la description.
isaacg
1
L'ordre de sortie spécifié est-il requis ou uniquement les valeurs?
Jonathan Allan
@ Satan'sSon Pas de rembourrage avec 0s.
ctrl-shift-esc
1
@JonathanAllan L'ordre de sortie spécifié est requis.
ctrl-shift-esc

Réponses:

13

Pyth, 18 octets

u+QiR2smc2+0dt#.BM

Suite de tests

Ce code fait quelque chose de très délicat et intelligent avec ul'opérateur de point fixe de Pyth.

Le corps de la fonction, qui est tout autre que le u, est assez simple:

+QiR2smc2+0dt#.BM
+QiR2smc2+0dt#.BMG    Implicit variable
                      G will store the list of numbers from the previous iteration.
              .BMG    Map each number to its binary representation
            t#        Filter out the ones of length 1 (0 and 1)
      m               Map the remaining binary
         +0d          Prefix with a 0
       c2             Chop in half.
                      Since c puts the larger half first, prefixing with a 0
                      makes the chop work out right, and doesn't change the value.
     s                Concatenate
  iR2                 Map back to binary
+Q                    Add the input to the front of the list

Ce code supprime les 0 et les 1, divise chaque nombre et ajoute l'entrée devant.

u exécutera cette fonction sur le résultat précédent de la fonction jusqu'à ce que le résultat cesse de changer.

Quelle valeur initiale uutilise-t-on? C'est la partie intelligente: le code ne spécifie pas la valeur à utiliser, il utilise donc par défaut l'entrée. Mais l'entrée n'est pas une liste de nombres - c'est un nombre. Pyth contraint implicitement le nombre sur le premier temps à travers la boucle à la plage du nombre - [0, 1, ..., Q-1]. Cela ne ressemble en rien à la sortie que nous voulons obtenir. Heureusement, utrouvera le résultat correct quelle que soit l'entrée initiale - la sortie souhaitée est le seul point fixe de la fonction, et une application répétée l'atteindra toujours.

Regardons les valeurs intermédiaires du programme avec l'entrée 7 . J'ai mis en évidence le préfixe du résultat qui est garanti d'être correct, quelle que soit l'entrée initiale:

  1. 7(Implicitement [0, 1, 2, 3, 4, 5, 6])

  2. [7,1, 0, 1, 1, 1, 0, 1, 1, 1, 2]

  3. [7, 1, 3,1, 0]

  4. [7, 1, 3, 1, 1]

Quelle est la sortie.


Python compressé, 16 octets

Notez que puisque Pyth utilise uniquement la plage 0-127 de l'ASCII, il peut être compressé en utilisant un codage 7 bits plutôt qu'un codage 8 bits. Ainsi, le programme ci-dessus peut être compressé en 16 octets. Le programme résultant est:

ꮎ�L����[
    ���4

hexdump:

0000000: eaae 8e9a 4cb9 edc6 c95b 0c9d 11ae 8534  ....L....[.....4

L'interprète se trouve ici . Fournissez l'entrée comme argument de ligne de commande.

La page de codes de ce langage (Packed Pyth) est la plage 0-127 de l'ASCII, et chaque caractère est représenté avec 7 bits, complété à la fin. Ainsi, le vidage hexadécimal illisible ci-dessus représente:

u+QiR2smc2+0dt#.BM

Mais en 16 octets.

isaacg
la source
6

05AB1E , 21 20 18 17 octets

,¸[Žrbvy0ì2äCʒ=1›

Essayez-le en ligne!

Explication

,¸[Žrbvy0ì2äCʒ=1›   Argument n
,¸                  Print n and push n as array
  [Ž                Loop until stack is empty
    r               Reverse stack
     b              Convert elements in array to binary
      v             For each y in array
       y0ì2ä        Prepend '0' to y and split it into 2 elements
                    (the first element will take the additional character)
            C       Convert elements to decimal
             ʒ=1›   Keep only elements greater than 1, while printing each element
kalsowerus
la source
@JonathanAllan Yep l'a corrigé maintenant. Semble être un problème que les exemples ne couvrent pas, merci :)
kalsowerus
ʒ- Cette nouvelle page de code ... Depuis quand est 05AB1E Jelly? Moi j'aime.
Urne Magic Octopus
4

JavaScript (ES6), 99 octets

Cela semble un peu trop long. Il pourrait y avoir un meilleur moyen d'obtenir la bonne commande.

f=(n,p=(a=[],1),i=33-Math.clz32(n)>>1)=>(a[p]=n)>1?f(n>>i,p*=2)&&f(n&(1<<i)-1,p+1):a.filter(n=>1/n)

Démo

Arnauld
la source
4

Gelée , 21 20 octets

-1 octet en supprimant une chaîne monadique, puis en traitant la conséquence de la conversion d'une liste vide du binaire en donnant 0 plus tard.

ỊÐḟBUœs€2UḄF
WÇÐĿṖUF

Un lien monadique prenant un numéro et renvoyant la liste spécifiée.

Essayez-le en ligne!

Comment?

ỊÐḟBUœs€2UḄF - Link 1, perform an iteration: list of numbers
 Ðḟ          - filter out if:
Ị            -   insignificant (absolute value <= 1 - hence any 0s or 1s)
   B         - convert to a binary list (vectorises)
    U        - upend (reverse each)
     œs€2    - split €ach into 2 equal chunks (the first half is longer if odd ...hence
         U   - upend (reverse each)         ...this upend and the previous one)
          Ḅ  - convert from binary list to number (vectorises, although when the filter
             -                                     removes everything a zero is yielded)
           F - flatten the resulting list of lists to a single list

WÇÐĿṖUF - Main link: number
W       - wrap in a list
  ÐĿ    - loop and collect results until no change occurs:
 Ç      -   call last link (1) as a monad
    Ṗ   - pop (remove the last element - a list containing a single zero which results
        -     from the effect of Ḅ when link 1's input only contained ones and zeros)
     U  - upend (put the iterations into the required order)
      F - flatten to yield a single list
Jonathan Allan
la source
Comment cela marche-t-il?
caird coinheringaahing
@ Satan'sSon J'ai ajouté une explication tout à l'heure
Jonathan Allan
Vous l'avez ajouté en même temps que j'ai commenté: D
caird coinheringaahing
@ ØrjanJohansen les deux façons ont le même coût en octets
Jonathan Allan
Oh, je n'ai pas vu la réponse Pyth en premier, qui a déjà utilisé cette astuce.
Ørjan Johansen
2

Java 7, 541 octets

import java.util.*;List l=new ArrayList(),L=new ArrayList();String c(int n){l.add(x(n));return a(n+" ",l,n);}String a(String r,List q,Integer n){boolean e=q.equals(l),E=q.equals(L);if(e)L.clear();else l.clear();for(String i:new ArrayList<String>(q)){int s=i.length()/2,a=n.parseInt(i.substring(0,s),2),z=n.parseInt(i.substring(s),2);r+=a+" "+z+" ";if(e&a>1)L.add(x(a));if(e&z>1)L.add(x(z));if(E&a>1)l.add(x(a));if(E&z>1)l.add(x(z));}if(e&L.size()>0)r=a(r,L,n);if(E&l.size()>0)r=a(r,l,n);return r;}String x(Integer n){return n.toString(n,2);}

Garder l'ordre d'origine m'a foutu pendant longtemps, sinon ce ne serait qu'une boucle facile et un principe d'appel récursif. Pourtant, défi amusant à comprendre tout en conservant la commande.

Explication:

import java.util.*;                    // Required import for List and Array List

List l=new ArrayList(),L=new ArrayList(); 
                                       // Two Lists on class-level

String c(int n){                       // Method (1) with integer parameter and String return-type
  l.add(x(n));                         //  Start by adding the binary-String of the input integer to list `l`
  return a(n+" ",l,n);                 //  And let the magic begin in method `a` (2)
}                                      // End of method (1)

String a(String r,List q,Integer n){   // Method (2) with a bunch of parameters and String return-type
  boolean e=q.equals(l),E=q.equals(L); //  Determine which of the two class-level Lists the parameter-List is
  if(e)                                //  If it's `l`:
    L.clear();                         //   Empty `L`
  else                                 //  If it's `L` instead:
    l.clear();                         //   Empty `l`
  for(String i:new ArrayList<String>(q)){
                                       //  Loop over the input list (as new ArrayList to remove the reference)
    int s=i.length()/2,                //   Get the length of the current item in the list divided by 2
                                       //   NOTE: Java automatically floors on integer division,
                                       //   which is exactly what we want for the splitting of odd-length binary-Strings
    a=n.parseInt(i.substring(0,s),2),  //   Split the current binary-String item in halve, and convert the first halve to an integer
    z=n.parseInt(i.substring(s),2);    //   And do the same for the second halve
    r+=a+" "+z+" ";                    //   Append the result-String with these two integers
    if(e&a>1)                          //   If the parameter List is `l` and the first halve integer is not 0:
      L.add(x(a));                     //    Add this integer as binary-String to list `L`
    if(e&z>1)                          //   If the parameter List is `l` and the second halve integer is not 0:
      L.add(x(z));                     //    Add this integer as binary-String to List `L`
    if(E&a>1)                          //   If the parameter List is `L` and the first halve integer is not 0:
      l.add(x(a));                     //    Add this integer as binary-String to List `l`
    if(E&z>1)                          //   If the parameter List is `L` and the second halve integer is not 0:
      l.add(x(z));                     //    Add this integer as binary-String to List `l`
  }                                    //  End of loop
  if(e&L.size()>0)                     //  If the parameter List is `l` and List `L` now contains any items:
    r=a(r,L,n);                        //   Recursive call with List `L` as parameter
  if(E&l.size()>0)                     //  If the parameter List is `L` and List `l` now contains any items:
    r=a(r,l,n);                        //   Recursive call with List `l` as parameter
  return r;                            //  Return the result-String with the now appended numbers
}                                      // End of method (2)

String x(Integer n){                   // Method (3) with Integer parameter and String return-type
  return n.toString(n,2);              //  Convert the integer to its Binary-String
}                                      // End of method (3)

Code de test:

Essayez-le ici.

import java.util.*;
class M{
  List l=new ArrayList(),L=new ArrayList();String c(int n){l.add(x(n));return a(n+" ",l,n);}String a(String r,List q,Integer n){boolean e=q.equals(l),E=q.equals(L);if(e)L.clear();else l.clear();for(String i:new ArrayList<String>(q)){int s=i.length()/2,a=n.parseInt(i.substring(0,s),2),z=n.parseInt(i.substring(s),2);r+=a+" "+z+" ";if(e&a>1)L.add(x(a));if(e&z>1)L.add(x(z));if(E&a>1)l.add(x(a));if(E&z>1)l.add(x(z));}if(e&L.size()>0)r=a(r,L,n);if(E&l.size()>0)r=a(r,l,n);return r;}String x(Integer n){return n.toString(n,2);}

  public static void main(String[] a){
    M m=new M();
    System.out.println(m.c(255));
    m.l.clear();
    m.L.clear();
    System.out.println(m.c(225));
    m.l.clear();
    m.L.clear();
    System.out.println(m.c(32));
  }
}

Production:

255 15 15 3 3 3 3 1 1 1 1 1 1 1 1 
225 14 1 3 2 1 1 1 0 
32 4 0 1 0 
Kevin Cruijssen
la source
2

Python 2 , 110 octets

l=[input()];i=1
while i:
 z=0
 for k in l[-i:]:
	if k>1:b=~-len(bin(k))/2;l+=[k>>b,k&2**b-1];z+=2
 i=z
print l

Essayez-le en ligne!

ovs
la source
2

Rétine , 142 octets

.+
$*
+`(1+)\1
${1}0
01
1
{`.+$
$&¶<$&>
+`;(\d*)>
>;<$1>
<.>

{`(\d)>
>$1
}`<(\d)
$1<
<>
;
\b0+\B

}`^;|;\B

¶
;
;;

1
01
+`10
011
0\B

1+
$.&

Essayez-le en ligne!

Neil
la source
2

PHP, 132 octets

for($r=[$argn];""<$n=$r[+$i++];)$n<2?:[$r[]=bindec(substr($d=decbin($n),0,$p=strlen($d)/2)),$r[]=bindec(substr($d,$p))];print_r($r);

Essayez-le en ligne!

Jörg Hülsermann
la source
Cela ne fonctionne pas, selon le système Try it en ligne de cette page,
Martin Barker
@MartinBarker que voulez-vous dire?
Jörg Hülsermann
tio.run/nexus/… => Array( [0] => 225 [1] => 14 [2] => 1 [3] => 3 [4] => 2 [5] => 1 [6] => 1 [7] => 1 [8] => 0 )quand ce n'est pas le cas = 255 15 15 3 3 3 3 1 1 1 1 1 1 1 1
Martin Barker
@MartinBarker Vous devez modifier l'entrée dans l'en-tête Version. Modifier la variable $argnCette variable est disponible si vous exécutez PHP à partir de la ligne de commande avec l' -Roption. Voici un exemple de saisie 255 Essayez-le en ligne!
Jörg Hülsermann
C'est ce que j'essayais de dire que cela ne fonctionnait pas selon le système d'essai en ligne. (lié dans le message)
Martin Barker
1

Rubis , 102 octets

f=->*a{a==[]?[]:a+=f[*a.map{|i|s='%b'%i;i>1?[s[0...h=s.size/2].to_i(2),s[h..-1].to_i(2)]:[]}.flatten]}

Essayez-le en ligne!

Encre de valeur
la source
1

Rubis , 98 octets

f=->*a{a==[]?a:a+=f[*a.flat_map{|i|s='%b'%i;i>1?[s[0...h=s.size/2].to_i(2),s[h..-1].to_i(2)]:[]}]}

Essayez-le en ligne!

Simplement une optimisation de base de la réponse de Value Ink : utilisez flat_map au lieu de map ... flatten, et utilisez

a==[]?a au lieu de a==[]?[]

Jenkar
la source