Trova il binarray!


24

Definiamo un binarray come un array che soddisfa le seguenti proprietà:

  • non è vuoto
  • il primo valore è a 1
  • l'ultimo valore è a 1
  • tutti gli altri valori sono 0o1

Ad esempio, l'array [ 1, 1, 0, 1 ]è un binarray valido .

L'obiettivo

Dato un array non vuoto A di numeri interi non negativi e un numero intero positivo N , il tuo compito è trovare un binarray B di lunghezza N che consenta di generare A sommando un numero illimitato di copie di B , spostato da un numero illimitato di posizioni.

Esempio

A = [ 1, 1, 2, 4, 1, 2, 2, 1, 0, 1, 0, 1, 1, 0, 1 ]
N = 4

Per questo input, il binarray B = [ 1, 1, 0, 1 ] sarebbe una risposta valida perché possiamo fare:

  [ 1, 1, 0, 1 ]
+       [ 1, 1, 0, 1 ]
+       [ 1, 1, 0, 1 ]
+          [ 1, 1, 0, 1 ]
+                   [ 1, 1, 0, 1 ]
+                                  [ 1, 1, 0, 1 ]
  -----------------------------------------------
= [ 1, 1, 2, 4, 1, 2, 2, 1, 0, 1, 0, 1, 1, 0, 1 ]

Regole

  • L'input può essere preso in qualsiasi formato ragionevole.
  • L'output può essere una matrice nativa (ad esempio [1, 1, 0, 1]) o una stringa binaria con o senza un separatore (ad esempio "1,1,0,1"o "1101")
  • Ti viene richiesto solo di stampare o restituire un binarray valido . In alternativa, puoi scegliere di stamparli o restituirli tutti quando esistono diverse soluzioni.
  • Non è necessario supportare input che non portano a nessuna soluzione.
  • La somma può includere gli zeri impliciti che non si sovrappongono con qualsiasi copia di B . Il secondo zero nella somma sopra è uno zero implicito.
  • Si può presumere che la dimensione massima di A sia 100 e la dimensione massima di B sia 30.
  • Questo è code-golf, quindi vince la risposta più breve in byte. Sono vietate le scappatoie standard.

Casi test

Input : N = 1 / A = [ 1, 2, 3, 4, 5 ]
Output: [ 1 ]

Input : N = 2 / A = [ 1, 2, 100, 99 ]
Output: [ 1, 1 ]

Input : N = 3 / A = [ 1, 1, 1 ]
Output: [ 1, 1, 1 ]

Input : N = 3 / A = [ 1, 1, 3, 2, 2 ]
Output: [ 1, 1, 1 ]

Input : N = 3 / A = [ 1, 0, 2, 1, 1, 1, 0, 0, 1, 0, 1 ]
Output: [ 1, 0, 1 ]

Input : N = 4 / A = [ 1, 2, 2, 2, 1 ]
Output: [ 1, 1, 1, 1 ]

Input : N = 4 / A = [ 1, 1, 2, 4, 1, 2, 2, 1, 0, 1, 0, 1, 1, 0, 1 ]
Output: [ 1, 1, 0, 1 ]

Input : N = 4 / A = [ 1, 1, 0, 2, 1, 0, 1 ]
Output: [ 1, 0, 0, 1 ] or [ 1, 1, 0, 1 ]

Input : N = 5 / A = [ 1, 3, 6, 9, 8, 6, 3, 4 ]
Output: [ 1, 1, 1, 0, 1 ]

Input : N = 8 / A = [ 2, 1, 0, 2, 3, 3, 1, 2, 1 ]
Output: [ 1, 0, 0, 1, 1, 1, 0, 1 ]

Input : N = 10 / A = [ 1, 2, 1, 2, 2, 1, 3, 3, 3, 2, 3, 0, 2, 1, 1, 0, 1 ]
Output: [ 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 ]

Input : N = 13 / A = [ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 ]
Output: [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ]

Input : N = 5 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 1, 1, 1, 1 ]

Input : N = 6 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 0, 0, 0, 0, 1 ]

Input : N = 7 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 1, 0, 0, 0, 1, 1 ]

Input : N = 9 / A = [ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 ]
Output: [ 1, 0, 1, 0, 1, 0, 1, 0, 1 ]

Qual è il valore più grande Nche dovrebbe essere ragionevolmente supportato?
Neil

@Neil Ho aggiunto limiti di dimensione sia su A che su B.
Arnauld

1
@ fənɛtɪk Forse, ma per N=4, A = [ 1, 1, 2, 4, 1, 2, 2, 2, 1, 2, 2, 1, 2, 0, 1 ], si ottiene 30459 che è divisibile per entrambi 11 e ancora 13 solo uno di [ 1, 1, 0, 1 ]ed [ 1, 0, 1, 1 ]è una risposta valida.
Neil,

1
@ fəˈnɛtɪk Questi numeri non sono scritti nella base 2, quindi non si applicano le regole dell'aritmetica. Ad esempio, non è possibile trasportare esplicitamente durante l'aggiunta.
BallpointBen,

2
Aggiungi questi casi di test, che sembrano infrangere quasi tutte le risposte postate: N = 3, A = [1, 0, 2, 0, 2, 0, 1], output = [1, 0, 1]; N = 3, A = [1, 1, 1, 0, 0, 0, 1, 1, 1], output = [1, 1, 1].
Anders Kaseorg,

Risposte:


8

PHP, 105 92 90 86 byte

La soluzione di Jörg fissa e giocava a golf:

for($b=1+2**$argv[1];;)--$argc>1?$s+=$argv[$argc]*2**$i++:$s%($b-=2)||die(decbin($b));

prende Ndal primo argomento della riga di comando, valori dopo quello; eseguirlo -ro testarlo online .
stampa il numero binario (formato 10001); stampa una soluzione non valida o si esaurisce se non esiste una soluzione valida.

prima versione (ora 97 byte) che non stampa nulla per input non valido: testarlo online

for($b=1+$m=2**$argv[1];$m/2<=$b;)--$argc>1?$s+=$argv[$argc]*2**$i++:$s%($b-=2)||die(decbin($b));

abbattersi

for($b=1+$m=2**$argv[1];$m/2<=$b;)  # second loop: loop $b from 2^N-1 by -2 to 2^(N-1)
--$argc>1                           # first loop: decrease $argc ...
    ?$s+=$argv[$argc]*2**$i++           # while $argc>1: binary sum from last to 2nd argument
    :$s%($b-=2)||die(decbin($b));       # later: if $b divides $s, print in binary and exit

Bello, non potresti raggiungere un numero di byte inferiore a 100?
Jörg Hülsermann,

1
@ JörgHülsermann che potrei.
Tito

Pensiero pesante. So prima che stai meglio. Spero che tu possa contenere il conteggio di byte più basso
Jörg Hülsermann

1
Su N = 3, A = [1, 0, 2, 0, 2, 0, 1], questo restituisce in modo errato111 dove l'unico risultato corretto è [1, 0, 1].
Anders Kaseorg,

8

PHP , 219 byte

<?for(list($g,$z)=$_GET,$d=~-$l=2**$z;$d>=$l/2;max(array_diff_assoc($r,$g)?:[0])?:$o[]=$b,$d-=2)for($r=[],$b=decbin($d),$k=0;$k<count($g);$k++)for($u=$g[$k]-$r[$k],$i=0;$i<$z;$i++)$u<1?:$r[$k+$i]+=$u*$b[$i];print_r($o);

Provalo online!

-4 byte usando [$g,$z]=$_GETPHP 7.1 invece dilist($g,$z)=$_GET


Sembra che restituisca sia una [1,0,1,0,1,0,1,0,1]risposta valida ( ) che una non valida ( [1,0,0,0,1,0,1,1,1]) per l'ultimo caso di test.
Arnauld,

-8 byte: while($_GET[0])$s+=2**$i++*array_pop($_GET[0]);. -5 byte: range(1|.5*$m=2**$_GET[1],$m,2).
Tito

@Arnauld Sì, dovrei dare come output solo il binarray più alto per rendere valida questa soluzione
Jörg Hülsermann

2
@ fəˈnɛtɪk Sono d'accordo con la tua matematica, ma la sfida è trovare un modello che possa essere riassunto esattamente in A, non una disposizione equivalente. Qui avremmo [ 1,0,1,1,1,0,2,2,2,2,2,1 ].
Arnauld,

1
-1 byte con for($g=$_GET[0];$g;).
Tito

3

Python, 166 byte

def f(a,n):
 for i in range(1<<n-1,1<<n):
  b=bin(i)[2:];u,v=(int(('0{:0>%d}'%sum(a)*len(s)).format(*s))for s in[a,b])
  if u%v<1>int(str(u//v*10)[::~sum(a)]):yield b

Provalo online!

Come funziona

Considerare A e B come le cifre di base k numeri u e v . Ad esempio (useremo k = 1000 per l'illustrazione):

A = [1, 2, 1, 3, 2, 1, 2]
B = [1, 0, 0, 1]
u = 1 002 001 003 002 001 002
v = 1 000 000 001

Come hanno notato molti degli altri risponditori, se B è una risposta valida, allora u è divisibile per v . In questo caso,

u = 1 002 001 002 ⋅ v

Questo quoziente, tradotto di nuovo nell'array [1, 2, 1, 2], ci dice esattamente quante copie di B abbiamo bisogno di spostare in ciascuna posizione.

  [1, 0, 0, 1]
+    [1, 0, 0, 1]
+    [1, 0, 0, 1]
+       [1, 0, 0, 1]
+          [1, 0, 0, 1]
+          [1, 0, 0, 1]
-----------------------
  [1, 2, 1, 3, 2, 1, 2]

(Perché? Perché è esattamente per quanto tempo funziona la moltiplicazione in base k .)

Ciò che gli altri risponditori non hanno notato è che la condizione di cui sopra non è sufficiente . Per esempio:

A = [1, 2, 1, 3, 2, 1, 2]
B = [1, 1, 1, 1]
u = 1 002 001 003 002 001 002
v = 1 001 001 001
u = 1 000 999 002 ⋅ v

Matematicamente parlando, possiamo ancora tradurre quel quoziente nell'array [1, 1, −1, 2], che funziona benissimo se ci è permesso usare copie negative di B:

  [1, 1, 1, 1]
+    [1, 1, 1, 1]
       [1, 1, 1, 1]
+          [1, 1, 1, 1]
+          [1, 1, 1, 1]
-----------------------
  [1, 2, 1, 3, 2, 1, 2]

ma ovviamente la sfida non consente copie negative. Quindi abbiamo bisogno di un controllo aggiuntivo.

A tal fine, selezioniamo una base k = 10 e dove k > 10 ⋅ somma (A) e controlliamo che nessuna delle cifre k di base trabocchi nella cifra k di base successiva quando moltiplichiamo il quoziente per dieci. Cioè, ogni e th base dieci cifre, a partire dalla fine, nella rappresentazione base dieci volte del quoziente dieci, deve essere 0. Questo garantisce che il quoziente traduce in un array con elementi non negativi.


1
Adoro il tuo trucco di utilizzare una grande potenza di 10 come base per rendere più semplice la conversione della base.
Neil,

2

PHP, 213 byte

Allo stesso modo un po 'golfato

<?for($b=2**~-$l=$_GET[1];$b<2**$l;array_filter($t[$b++])?:$d[]=$o)for($g=count($t[$b]=$_GET[$i=0]);min($t[$b])>-1&$i<=$g-$l;$i++)for($e=$t[$b][$i],$k=0,$o=decbin($b);$k<$l;)$t[$b][$k+$i]-=$o[$k++]*$e;print_r($d);

Provalo online!

PHP, 344 byte prima funzionante

Dopo la mia prima risposta ho deciso di fare un tentativo più lungo che restituisca tutte le soluzioni valide.

<?foreach(range(2**($l=$_GET[1])-1,2**($l-1))as$b){$t[$b]=($g=$_GET[0]);for($i=0;$t[$b]&&$i<=count($g)-$l;$i++){$e=reset($y=array_slice($t[$b],$i,$l));foreach(str_split(decbin($b))as$k=>$v)$t[$b][$k+$i]=$y[$k]-$e*$v;if(min($t[$b])<0)unset($t[$b]);}}foreach($t as$k=>$v)if(max($v)>0)unset($t[$k]);echo join(",",array_map(decbin,array_keys($t)));

Versione online

Abbattersi

foreach(
    range(2**($l=$_GET[1])-1
    ,2**($l-1)
    ) # make decimal range of a binarray with given length
    as$b){
$t[$b]=($g=$_GET[0]); # make a copy for each possible solution pattern
    for($i=0;$t[$b]&&$i<=count($g)-$l;$i++){ # Loop till solution is valid or reach last digit
        $e=reset($y=array_slice($t[$b],$i,$l)); # take first value of a sequence with the length
        foreach(str_split(decbin($b))as$k=>$v)
            $t[$b][$k+$i]=$y[$k]-$e*$v; # replace values in copy
        if(min($t[$b])<0)unset($t[$b]); # kill solution if a minimum <0 exists
    }
}
foreach($t as$k=>$v)if(max($v)>0)unset($t[$k]); # drop all solutions where the sum is not zero 


echo join(",",array_map(decbin,array_keys($t))); #Output all solutions

Questo sembra funzionare per N ≥ 2, ma non riesce in N = 1 casi, come il primo caso di test nella sfida.
Anders Kaseorg,

@AndersKaseorg Ora supporta i casi N = 1, è sufficiente impostare a =nel primo loop per la versione più breve Nella versione più grande deve eliminare quattro byte
Jörg Hülsermann

1

Python, 205 byte

def f(a,l):
 b=lambda s:b(s[:-1])*sum(a)*8+int(s[-1])if s else 0
 c=lambda n:n and(n/sum(a)/4%2 or c(n/sum(a)/8))
 for i in range(2**~-l,2**l):
  j=bin(i)[2:]
  if b(a)%b(j)<1 and not c(b(a)/b(j)):return j

Restituisce una stringa binaria senza separatore. Come sottolineato da @AndersKaseorg, ci sono input per i quali la soluzione di @ fəˈnɛtɪk non funziona perché la divisione rappresenta un coefficiente negativo che non è consentito. Per ovviare a questo, uso una base molto ampia e testare che non ci sono prestiti nella divisione.


Va bene, penso che questo sia un vero controesempio: f([1, 1, 1, 0, 0, 0, 1, 1, 1], 3)restituisce in modo errato 101.
Anders Kaseorg,

@AndersKaseorg Hmm, invertire l'ordine del loop aiuta o l'algoritmo è ancora fondamentalmente rotto?
Neil,

Penso che sia sostanzialmente rotto senza ulteriori controlli. La variante inversa non funziona f([1, 0, 2, 0, 2, 0, 1], 3)e entrambe le varianti diretta e inversa non funzionano f([1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0], 5).
Anders Kaseorg,

E anche se controlli che isia strano, entrambe le varianti avanti e indietro falliscono f([1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]*10, 5).
Anders Kaseorg,

1
@AndersKaseorg Ah sì, quando gcd (k, n) = 1, (x^kn-1)/(x^k-1)ha sempre (x^n-1)/(x-1)un fattore, che ingannano la soluzione di @ fəˈnɛtɪk in qualsiasi base.
Neil,

1

Pyth, 32 byte

f!|%FKiRJysQ,QT>#sQj/FKJ+L1^U2tE

Provalo online

Come funziona

                           ^U2tE   Cartesian power [0, 1]^(N - 1)
                        +L1        prepend 1 to every list
f                                  filter for lists T such that:
          sQ                         sum(A)
         y                           double
        J                            assign to J
      iR    ,QT                      convert [A, T] from base J
     K                               assign to K
   %F                                fold modulo
  |                                  logical OR with
                    /FK                fold integer division over K
                   j   J               convert to base J
               >#sQ                    filter for digits greater than sum(A)
 !                                   logical NOT

La strategia è simile alla mia risposta Python , tranne per il fatto che poiché Pyth ha i builtin per la conversione di base, possiamo usare una base k = 2 ⋅ (A) più efficiente e controllare direttamente che ogni cifra del quoziente sia al massimo della somma (A ).


1

Pari / GP , 77 74 96 80 byte

n->a->[v|d<-divisors(b=Pol(a)),(v=Vec(d))%2==v&&vecmin(Vec(b/d))>=0&&d%x&&#d==n]

Restituisce tutte le soluzioni.

Innanzitutto converte l'array ain un polinomio b. Quindi sceglie dai divisori bi polinomi in modo dtale che i coefficienti di dsiano tutti 1e 0, e i coefficienti di b / dsiano tutti non negativi, e d(0) = 1, e deg(d) = n + 1. Alla fine, li converte in array.

Provalo online!

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.