Dividimi a metà


15

Ti verrà dato un numero x, dove 0 <= x <= 2^32 - 1.

Dovresti generare un elenco di numeri in decimale, dopo la divisione ricorsiva in formato binario.

Esempi:

Esempio 1:

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

L'elenco attuale è giusto 255.

La rappresentazione binaria di 255è 1111 1111. Dividendolo, otteniamo 1111e 1111, che in decimali sono 15e 15.

Aggiungiamo quelli alla lista, quindi avremo 255 15 15.

Ora i numeri 15e 15serviranno da input e questi numeri devono essere divisi.

Facendo di nuovo, si ottiene ( 3 3da entrambe le 15s): 255 15 15 3 3 3 3.

Continuando la logica, l'elenco finale sarà 255 15 15 3 3 3 3 1 1 1 1 1 1 1 1. E poiché 1non può più essere diviso, l'uscita si interrompe.

Esempio 2:

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

L'elenco di partenza è 225.

La rappresentazione binaria di 225è 1110 0001. Dividendolo, otteniamo 1110e 0001, che in decimali sono 14e 1.

Aggiungendo quelli alla lista, otteniamo 225 14 1.

Ora i numeri 14e 1serviranno da input e questi numeri devono essere divisi.

Poiché 1non è divisibile, l'output sarà 225 14 1 3 2.

Esempio 3:

32 -> 32 4 0 1 0

Condizioni :

  1. Se il numero di cifre binarie è dispari, il primo numero avrà una cifra binaria in meno rispetto alla successiva. Esempio, 20 (10100)verrà diviso come 10e 100, con l'output decimale essendo 2e 4.
  2. Si applicano le regole standard per le scappatoie.
  3. 0s e 1s non si propagano ulteriormente.
  4. Il crash del programma per il tentativo di visualizzare troppi numeri è una condizione di uscita valida.

Solo un suggerimento, ma che dire di avere le cifre binarie riempite con 0s quando la lunghezza è dispari?
caird coinheringaahing del

1
@ Satan'sSon Se ti trovi davanti, questo equivale alla descrizione.
isaacg,

1
È richiesto l'ordine di uscita specificato o solo i valori?
Jonathan Allan,

@ Satan'sSon Nessuna imbottitura con 0s.
ctrl-shift-esc

1
@JonathanAllan È richiesto l'ordine di output specificato.
ctrl-shift-esc

Risposte:


13

Pyth, 18 byte

u+QiR2smc2+0dt#.BM

Suite di test

Questo codice fa qualcosa di molto complicato e intelligente u l'operatore a virgola fissa di Pyth.

Il corpo della funzione, che è tutto diverso da quello u, è abbastanza semplice:

+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

Questo codice rimuove 0 e 1, divide ogni numero e aggiunge l'input in primo piano.

u eseguirà questa funzione sul risultato precedente della funzione fino a quando il risultato non smette di cambiare.

Quale valore iniziale uutilizza? Questa è la parte intelligente: il codice non specifica quale valore utilizzare, quindi per impostazione predefinita è l'input. Ma l'input non è un elenco di numeri, è un numero. Pyth costringe implicitamente il numero nel tempo di pugno attraverso il loop all'intervallo del numero - [0, 1, ..., Q-1]. Non assomiglia affatto all'output che vogliamo ottenere. Per fortuna,u troverà il risultato corretto indipendentemente da quale sia l'input iniziale: l'uscita desiderata è l'unico punto fisso della funzione e l'applicazione ripetuta lo raggiungerà sempre.

Diamo un'occhiata ai valori intermedi del programma con l'input 7. Ho evidenziato il prefisso del risultato che è garantito per essere corretto, indipendentemente dall'input iniziale:

  1. 7(Implicitamente [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]

Qual è l'output.


Pyth compresso, 16 byte

Si noti che poiché Pyth utilizza solo l'intervallo 0-127 di ASCII, può essere compresso utilizzando una codifica a 7 bit anziché una codifica a 8 bit. Pertanto, il programma sopra può essere impacchettato in 16 byte. Il programma risultante è:

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

hexdump:

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

L'interprete si trova qui . Fornire l'input come argomento della riga di comando.

La tabella codici di questo linguaggio (Packed Pyth) è l'intervallo 0-127 di ASCII e ogni carattere è rappresentato con 7 bit, riempito alla fine. Pertanto, il hexdump sopra illeggibile sopra rappresenta:

u+QiR2smc2+0dt#.BM

Ma in 16 byte.


6

05AB1E , 21 20 18 17 byte

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

Provalo online!

Spiegazione

,¸[Ž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

@JonathanAllan Yep ora risolto. Sembra essere un problema gli esempi non coprono, grazie :)
Kalsowerus,

ʒ- Questa nuova tabella codici ... Da quando è 05AB1E Jelly? Mi piace.
Magic Octopus Urn

4

JavaScript (ES6), 99 byte

Questo sembra un po 'troppo lungo. Potrebbe esserci un modo migliore per ottenere l'ordine corretto.

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)

dimostrazione


4

Jelly , 21 20 byte

-1 byte rimuovendo una catena monadica e quindi occupandosi della conseguenza di un elenco vuoto convertito da binario che restituisce 0 in seguito.

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

Un collegamento monadico che prende un numero e restituisce l'elenco specificato.

Provalo online!

Come?

ỊÐḟ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

Come funziona?
caird coinheringaahing del

@ Satan'sSon Ho aggiunto una spiegazione proprio ora
Jonathan Allan,

L'hai aggiunto nello stesso momento in cui ho commentato: D
caird coinheringaahing

@ ØrjanJohansen in entrambi i modi hanno lo stesso costo in byte
Jonathan Allan,

Oh, non ho visto prima la risposta di Pyth, che già utilizzava quel trucco.
Ørjan Johansen,

2

Java 7, 541 byte

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);}

Mantenere l'ordine originale mi ha fregato alla grande, altrimenti sarebbe solo un semplice ciclo e principio di chiamata ricorsiva. Tuttavia, sfida divertente da capire mantenendo l'ordine.

Spiegazione:

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)

Codice di prova:

Provalo qui.

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));
  }
}

Produzione:

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 


2

Retina , 142 byte

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

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

}`^;|;\B

¶
;
;;

1
01
+`10
011
0\B

1+
$.&

Provalo online!


2

PHP, 132 byte

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);

Provalo online!


Questo non funziona, secondo il sistema Try it online in questa pagina,
Martin Barker,

@MartinBarker cosa intendi?
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 )quando non è = 255 15 15 3 3 3 3 1 1 1 1 1 1 1 1 1
Martin Barker

@MartinBarker È necessario modificare l'input nella versione dell'intestazione. Modifica la variabile $argnQuesta variabile è disponibile se si esegue PHP dalla riga di comando con l' -Ropzione. Ecco un esempio per l'ingresso 255 Provalo online!
Jörg Hülsermann,

Questo è quello che stavo cercando di dire che non funzionava secondo il sistema di prova online. (collegato nel post)
Martin Barker,


1

Rubino , 98 byte

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)]:[]}]}

Provalo online!

Semplicemente un'ottimizzazione di base della risposta di Value Ink : usa flat_map invece di map ... flatten e usa

a==[]?a invece di a==[]?[]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.