Genera una tabella di ricerca con funzione binaria universale


19

Questo è tangenzialmente collegato alla mia ricerca di inventare un linguaggio di programmazione esoterico .

Una tabella dei numeri binari 0 .. 15 può essere utilizzata per implementare una funzione binaria universale mediante operazioni di indicizzazione. Dati due ingressi a 1 bit X e Y, tutte le 16 possibili funzioni possono essere codificate in un codice operativo a 4 bit.

X Y  F|0 1 2 3 4 5 6 7 8 9 A B C D E F
- -    - - - - - - - - - - - - - - - -  
0 0    0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1    0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0    0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
1 1    0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
       -     -   - -   -   -   -   - -
       0    ~X  ~Y ^   &   Y   X   | 1
      ZERO    NOT-Y   AND         OR
          NOT-X   XOR              ONE

Quindi questo set di 16 funzioni può essere applicato agli ingressi binari come funzione

U (f, x, y): (f >> ((x << 1) | y)) & 1 ,

o

U (f, x, y): (f / 2 ^ (x × 2 + y))% 2 ,

o con indicizzazione o partizionamento matriciale.

Sarà utile conoscere il modo più compatto di rappresentare o generare una tale tabella di valori per ogni possibile linguaggio da costruire su questo tipo di operazione binaria.

L'obiettivo. il gol:

Genera questo output di testo esatto:

0101010101010101
0011001100110011
0000111100001111
0000000011111111

Questo è tutto! Vince il codice più corto.


2
Ho avuto un'intuizione che la famiglia APL avrebbe fatto bene qui. :)
luser droog


Sono accettate le nuove linee guida o finali?
Tito,

Sì, le newline extra vanno bene.
Luser droog

Risposte:


20

J, 10 (13?) Caratteri

|.|:#:i.16

Elenco numeri:

   i.16
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15`

al binario:

   #:i.16
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1

Trasporre:

   |:#:i.16
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

Inverso:

   |.|:#:i.16
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

Dobbiamo rimuovere gli spazi? Guardando il altra risposta J sembra lo facciamo avremo bisogno di aggiungere 3 caratteri e prendere in prestito il 1":da risposta di Jan .


1
Molto bello lo stile di spiegazione. +1 (anche dannatamente corto!)
Luser droog

Non appena ho visto la risposta di Peter's Golfscript ho capito che avrei potuto fare molto meglio. Bene, l'hai già fatto.
John Dvorak,

Bello vedere qualcosa di più corto di Golfscript ...
fuenfundachtzig


@luserdroog Wow. È un sacco di codice. Molto più leggibile del codice sorgente J però. :-) Molto bello.
Gareth

13

Python 2, 40

for n in 1,2,4,8:print 8/n*('0'*n+'1'*n)

7

APL (14)

Supponendo ⎕IO=0(questa è un'impostazione):

⎕D[⊖(4⍴2)⊤⍳16]

Spiegazione:

  • ⍳16: numeri [0,16)
  • (4⍴2)⊤: codifica ogni numero nella base 2 usando 4 cifre
  • : retromarcia orizzontale (quindi l'MSB finisce in cima)
  • ⎕D[... ]: selezionare questi valori da ⎕Dcui è la stringa 0123456789. (Una matrice numerica viene visualizzata con spazi tra i valori, una matrice di caratteri no. Quindi questo converte ogni bit numerico in uno dei caratteri '0' '1').

Il primo personaggio della fonte dovrebbe apparire come un quadrato o mi mancano ancora alcuni caratteri?
Tim Seguine,

@TimSeguine Sì, è un quadrato, chiamato quad nella letteratura APL. I nomi delle variabili che iniziano con quad sono variabili di sistema che cambiano l'ambiente. IO = "origine indice".
Luser droog

Salva un byte: (4⍴2)⊤2⊥⍣¯1
Adám il

6

Jelly , 42 7 byte (non concorrenti)

⁴ḶBUz0Y

Provalo online!

Grazie a Dennis per il suo aiuto. Ecco il primo messaggio, ecco l'ultimo (si sono verificate anche altre discussioni). Con il suo aiuto, apparentemente (quasi) ho radicato il punteggio.


Poiché la lingua è più recente della domanda, non posso accettarla come risposta. Sicuramente in corsa per la generosità, però!
Luser droog

@luserdroog Va bene. Ma, ho pensato che la sfida fosse più recente.
Erik the Outgolfer,

So cosa intendi, non mi sembra che sia stato tanto tempo fa che l'ho pubblicato. Ma anche il mio inca2, a 2 anni, è una lingua troppo giovane.
Luser droog

+1 per il codegolf da 42 a 7. È qualcosa che non vedi tutti i giorni (se non fatto apposta).
Kevin Cruijssen,

1
@KevinCruijssen Perché mai dovrebbe essere fatto apposta? Sono solo un principiante di Jelly (conosco bene Python 2 e 3), quindi l'ho fatto su una stringa, mentre "ho bisogno di trattare Jelly come un linguaggio manipolatore di array".
Erik the Outgolfer,


4

GolfScript ( 18 17 15 caratteri)

(Grazie a Howard)

16,zip{','-~n}%

Non capisco perché il 10 caratteri

16,zip{n}/

non funziona; Sospetto che un bug nell'interprete standard abbia come risultato tipi non supportati nello stack.

Un'alternativa a 18 caratteri che capisco pienamente è:

4,{2\?.2,*$8@/*n}%

Un approccio più matematico è un po 'più lungo, a 28 caratteri:

4,{2.@??)2.4??.@/+2base(;n}/

Molto di questo è per la conversione di base e zero padding. Senza quelli, scende a 19 caratteri,

4,{2.@??)2.4??\/n}/

con uscita

21845
13107
3855
255

È stato chiesto un risultato esatto: perché dovrebbe 16,zip{n}/funzionare allora?
Howard,

D'altra parte puoi fare16,zip{','-~n}%
Howard il

@Howard, penso che zipdovrebbe restituire una matrice di array, ma in realtà sembra restituire una matrice di array Ruby (è la mia ipotesi migliore). Qualunque siano gli elementi, l'applicazione di `` `` a loro non influisce sul modo in cui stampano, il che è diverso da qualsiasi dei 4 tipi di dati GolfScript. Hai ragione, ','-sembra che li trasformi in normali array: un bel trucco.
Peter Taylor,

Sembra produrre 4 righe extra di zeri qui
aditsu,

@aditsu, lavora sulla demo online . Mi chiedo perché la differenza. Versione di Ruby, forse?
Peter Taylor,

3

CJam - 16

4,{G,f{\m>2%}N}/

Codice java equivalente (come spiegazione):

public class Lookup {
    public static void main(final String... args) {
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 16; ++j) {
                System.out.print((j >> i) % 2);
            }
            System.out.println();
        }
    }
}

3

Javascript (ECMA6), 67

s=(k,n)=>n-.5?s((k<<n/2)^k,n/2)+"0".repeat(n)+k.toString(2)+"\n":"" 

Per usare questo, chiama

s(255,8)

Bitshift!
E anche XOR e un po 'di ricorsione.

La prima cosa da notare è che se prendiamo una linea e la sposti (numero di 0 continui) / 2 a sinistra, otteniamo un XOR carino per ottenere la riga successiva.

Per esempio,

0000000011111111 //line 4
0000111111110000 //shifted 4 to the left

XOR questi ci danno per bit

0000111100001111 //XOR'ed. This is line 3!

che è la riga successiva (riga 3).
Applicando lo stesso processo per la linea 3, spostiamo 2 a sinistra e otteniamo ...

0000111100001111
0011110000111100

XOR dà

0011001100110011

che è la riga 2.
Nota che l'importo che spostiamo dimezza ogni volta.
Ora chiamiamo semplicemente questa funzione in modo ricorsivo, con 2 argomenti. Il valore intero di questa linea e N, che è quanto dobbiamo spostare. Quando ripetiamo, passa semplicemente il valore XOR spostato e n / 2.

"0".repeat(n)

è il pad di 0 all'inizio di ogni riga perché toString elimina 0 iniziali.


+1 Molto bello. Non avevo notato quello schema prima.
Luser droog

Un paio di bye possono essere tagliati spostando n invece di dividerlo e sostituendo la nuova riga con una stringa di modello:s=(k,n)=>n?s((k<<n/2)^k,n>>1)+"0".repeat(n)+k.toString(2)+` `:""
Shaun H

2

J, 21 caratteri

1":<.2|(2^i.4)%~/i.16
  • i.16 è un elenco di 0..15
  • 2^i.4 è un elenco (1,2,4,8)
  • %~/ produce la tabella delle divisioni in cui l'argomento sinistro forma le righe ma è l'argomento giusto per la divisione
  • 2| calcola il resto dopo aver diviso [ogni cella] per due
  • <. piani che valgono 0 o 1
  • 1": formatta la tabella con un carattere per cella

Sento che floornon dovrebbe essere necessario. Il dominio di 2|è già 0 o 1, giusto?
Luser droog

@luserdroog |funziona su float . 2|3.25lo è 1.25. Non lo vogliamo.
John Dvorak,

2

GolfScript, 19 caratteri

Un altro approccio GolfScript

4,{2\?{&!!}+16,%n}%

2

Rubino (44)

Noioso e lungo: basta stampare le rappresentazioni binarie con numeri 0 dei numeri.

[21845,13107,3855,255].map{|i|puts"%016b"%i}

2

poscritto 108 177 126 77 74 70

[43690 52428 61680 65280]
{16{dup 2 mod =only 2 idiv}repeat<>=}forall

Invertire i valori per un metodo di mod- off più semplice .

151 131 119

Applicare un approccio più APL -ish. modifica: sostituito il taglio delle stringhe e la compressione dell'array con indicizzazione e for-loop.

[[0 1 15{}for]{16 add 2 5 string cvrs}forall]4 
-1 1{0 1 15{2 index exch get 1 index 1
getinterval =only}for pop<>=}for

rientrato:

[[0 1 15{}for]{16 add 2 5 string cvrs}forall]
4 -1 1{ % [] i
    0 1 15{ % [] i j
        2 index exch get % [] i [](j)
        1 index 1  % [] i [](j) i 
        getinterval  % [] i [](j)<i>
        =only  % [] i
    }for 
    pop<>= % []
}for

La reimplementazione delle funzioni utilizzate nella risposta J vincente porta a questo (con un sacco di codice di supporto ).

-1 16 i + #: |: |.{{==only}forall()=}forall

iqui è un vettore basato su 1 descritto nelle Funzioni elementari di Iverson , quindi il -1 ... +da produrre 0 .. 15.


2

Perl (36 + 1)

+1 per say, come al solito. il doppio 0non è un refuso :)

map say((00x$_,1x$_)x(8/$_)),1,2,4,8

Non è necessario aggiungere 1 per say. perl -e'...'è standard e questo richiede perl -E'...', nessun aumento nel conteggio dei byte. Ad ogni modo, penso che sia stato deciso su Code Golf Meta che -M5.01è gratuito.
msh210

2

JavaScript (ECMA6), 108

Cercando un approccio diverso qui. Anche se è stato incoraggiato a utilizzare operatori binari, mi sono permesso di presentare questa soluzione poiché la sfida è anche la e stavo pensando: come posso ridurre la quantità di codice che rappresenta quei valori ...? Basi .

['gut','a43','2z3','73'].forEach(n=>{a=parseInt(n,36).toString(2);
alert(('00000000'+a).substr(a.length-8))})

(Interruzione di riga per comodità).

È un peccato che ho dovuto pasticciare con il riempimento con zeri iniziali, ma il punto di questo codice è semplicemente rappresentare il risultato binario di destinazione in Base 36, che sono esattamente quei gut, a43, 2z3, 73valori.

Nota: mi rendo conto che non sarà da nessuna parte vicino alla risposta vincente, ma solo per il gusto dell'idea ...


1
Stavo per fare praticamente la stessa cosa quando ho visto la tua. Ho preso fino a 92 byte con la tecnica da mia risposta a una domanda simile : alert(['gut','a43','2z3',73].map(n=>(1e8+parseInt(n,36).toString(2)).slice(-16)).join('\n')). Questo approccio utilizza newline anziché quattro alert()s.
NinjaBearMonkey


2

MATL ( non concorrenziale ), 8 byte

16:qYB!P

Provalo online!

Spiegazione

16:    % Generate range [1 2 ... 16]
q      % Subtract 1, element-wise
YB     % Convert to binary. Gives a 16×4 char array. Each original number is a row
!      % Transpose
P      % Reverse vertically. Implicitly display

2

CJam ( non concorrenziale ), 10 9 byte

Grazie a @Dennis per 1 byte di sconto!

Y4m*zW%N*

Provalo online!

Spiegazione

Y     e# Push 2
4     e# Push 4
m*    e# Cartesian power of 2 (interpreted as [0 1]) with exponent 4
z     e# Zip
W%    e# Reverse the order of rows
N*    e# Join with newlines. Implicitly display

2

JavaScript (ES6), 58 52 byte

Costruisce la stringa in modo ricorsivo.

f=(n=64)=>n--?f(n)+(!n|n&15?'':`
`)+(n>>(n>>4)&1):''

Come funziona

Questa ricorsione si basa sul fatto che il modello è costituito dalla rappresentazione binaria verticale di stuzzichini da 0x0 a 0xF:

  0101010101010101 bit #0 <- Y = 0
  0011001100110011 bit #1
  0000111100001111 bit #2
  0000000011111111 bit #3 <- Y = 3
  ----------------
  0123456789ABCDEF
  ^              ^
X = 0          X = 15

Pertanto, ogni posizione (X, Y) in questo modello può essere espresso come Y-esimo bit X: X & (1 << Y). Possiamo anche isolare questo bit con: (X >> Y) & 1. Invece di tenere traccia di X e Y, iteriamo una singola variabile nche varia da 0 a 63. Quindi, la formula diventa: (n >> (n >> 4)) & 1. In realtà è più facile iterare da 63 a 0, quindi la stringa è costruita in ordine inverso. In altre parole, il carattere n-1 è aggiunto alla sinistra del carattere n .

Come nota a margine, la ricorsione non porta nulla qui tranne il codice più breve.

Senza le interruzioni di riga, il codice è lungo 35 byte:

f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):''

Abbiamo bisogno di altri 17 byte per inserire le interruzioni di riga. Questo potrebbe essere ridotto a 14 byte se è accettabile un'interruzione di linea iniziale.

dimostrazione

f=(n=64)=>n--?f(n)+(!n|n&15?'':`
`)+(n>>(n>>4)&1):''

console.log(f());


In ideone con entrambe le lingue JavaScript non compilato nell'esapra sopra ce n'è uno lascia più .... È buona l'idea di una funzione ricorsiva ...
RosLuP

Cosa ci vorrebbe per dividere dopo i 35 byte?
Tito,

@Titus - Bene. A prima vista, non ho una buona soluzione per questo. Ecco un tentativo (molto brutto): (f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):'')().match(/.{16}/g).join`\n` (63 byte)
Arnauld,

hmm ... e .replace(/.{16}/g,"$0\n")ha la stessa lunghezza. Peccato.
Tito,

2

Bash + coreutils, 65 byte

Non il più breve, ma nemmeno il più lungo:

for i in {1,2,4,8};{ eval echo \$\[\({0..15}\&$i\)/$i];}|tr -d \ 

(L'ultimo personaggio è uno spazio)

Provalo online .


1

NARS2000 APL, 22

"01"[⊖1+(4⍴2)⊤(⍳16)-1]

Derivato dalla risposta APL di Marinus, che non sembra funzionare su NARS2000.

Genera vettore

      ⍳16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Passa alla base zero

      (⍳16)-1
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Genera forma per codifica

      (4⍴2)
2 2 2 2

Codificare

      (4⍴2)⊤(⍳16)-1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

Regola per l'indicizzazione basata su 1

      1+(4⍴2)⊤(⍳16)-1
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2

Asse primario inverso

      ⊖1+(4⍴2)⊤(⍳16)-1
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2

Indice

      "01"[⊖1+(4⍴2)⊤(⍳16)-1]
0101010101010101
0011001100110011
0000111100001111
0000000011111111

È possibile impostare ⎕IO su 0, in modo da non dover regolare per l'indicizzazione basata su 1. Questo lo porta a 16 caratteri.
Elias Mårtenson,

Sì, ma temo che sia troppo simile all'altra risposta APL e non meriterei di essere qui.
Luser droog

1

C, 73 caratteri

i;main(){for(;i<64;)i&15||puts(""),putchar(48|1&~0xFF0F0F33335555>>i++);}

Questa è solo una soluzione generale per l'output di 64 bit in quattro blocchi a 16 bit; devi solo cambiare il numero 0xFF0F0F33335555per generare un'altra sequenza di bit.

semplificato e non golfato:

int main() {
    int i;
    for(i = 0; i < 64; i++) {
        if(i % 16 == 0) {
            puts("");
        }
        int bit = ~0xFF0F0F33335555 >> i;
        bit &= 1;
        putchar('0' + bit);
    }
}

1

Haskell, 73

Yikes, 73 caratteri! Non posso per amore di Dio ottenere questo più piccolo però.

r=replicate
f n=r(div 8n)("01">>=r n)>>=id
main=mapM(putStrLn.f)[1,2,4,8]

La vera parte triste di questo è che se dovessi fare eco all'output usando bash, avresti bisogno solo di 74 caratteri.


1

JavaScript (ES5) 69

for(x="";4>x;x++){z="";for(n=0;16>n;)z+=1-!(n++&1<<x);console.log(z)}


1

inca2 ,33 27 24

4 16#(,`2|(~16)%.2^~4){D

Questo si basa sulla risposta di Jan Dvorak . inca2 è in grado di eseguire questo a partire dalle correzioni di bug di ieri. Tecnicamente non valido poiché la lingua è stata inventata dopo la domanda, ma l' invenzione di una lingua è stata parte del mio obiettivo nel porre la domanda. Quindi ecco un rimborso in segno di gratitudine per le altre risposte. :)

Spiegazione:

4 16#(,`2|(~16)%.2^~4){D
          (~16)               integers 0 .. 15 
                 2^~4         first 4 powers of 2: 1 2 4 8
          (~16)%.2^~4         division table
        2|                    mod 2 (and floor)
       `                      transpose
      ,                       ravel
     (               ){D      map to chars '0'..'9'
4 16#                         reshape to 4x16

Alcune parentesi non dovrebbero essere necessarie, ma a quanto pare ci sono alcuni problemi rimanenti con la mia interpretazione della grammatica. E "ravel => map => reshape" è davvero maldestro: la mappa deve essere più intelligente. Modificare: correzioni dei bug consentono l'eliminazione delle parentesi.


Fattorizzazione della conversione di base in una funzione separata N:x|y%.x^~1+[]/x.y produce questo19 Versione 16 caratteri.

4 16#(,`2N~16){D

E mentre sto barando comunque qui, sono andato avanti e ho reso questa funzione integrata. Ma, anche se è un funzione niladica (non richiede un argomento), non c'è supporto per le funzioni niladiche e deve essere fornita con un argomento fittizio.

inca2, 2

U0

1

Pyth 24/26

Il metodo più breve era la risposta di grc tradotta in Pyth che mi è sembrata economica, quindi ho fatto il mio metodo:

Miniera: 26 caratteri

 mpbjk*/8dS*d[0 1)[1 2 4 8

grc: 24 caratteri

Fd[1 2 4 8)*/8d+*\0d*\1d

1

C ++ 130

Converte esadecimale in binario

#define B std::bitset<16>
#define C(x) cout<<x<<endl;
void main(){
B a(0xFF),b(0xF0F),c(0x3333),d(0x5555);
C(d)C(c)C(b)C(a)
}

1

Haskell (Lambdabot), 47 byte

unlines$reverse$transpose$replicateM 4['1','0']

Un po 'economico perché usa trasporre da Data.List e replicateM da Control.Monad, tuttavia entrambi sono caricati di default da Lambdabot.

Inoltre, sono sicuro che ci sia spazio per miglioramenti, volevo solo condividere l'idea


1

Julia (39 byte)

La seconda sceneggiatura che ho mai scritto a Julia, devo ammettere che mi piace Julia, è una bella bestia.

hcat(map(x->collect(bin(x,4)),0:15)...)

ritorna

[0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 
 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]  

Spiegazione:

  • bin(x,4) - Converti int in numero intero binario con riempimento a 4 caratteri.
  • collect(_) - Dividi la stringa in array di caratteri.
  • map(x->_,0:15) - Fatelo per le prime 16 cifre dell'intervallo.
  • hcat(_...) - Splat e concatenare orizzontalmente in una matrice.

1

C 83 77 76 74 71

x;f(n){for(;x<4;x++,puts(""))for(n=0;n<16;)putchar(49-!(n++&(1<<x)));}

Abbastanza diretto.

x;
f(n){
    for(;x<4;x++,puts(""))
        for(n=0;n<16;)
            putchar(49-!(n++&(1<<x)));
}

1
C'è un facile salvataggio di 2 non utilizzando ?:e un altro salvataggio di 1 spostando a ++.
Peter Taylor,

Salvato 3 cambiando mainin f. lol
luser droog

1

R, 53 41 byte

Una traduzione della risposta di Python di @grc. Eliminato 12 byte dalla traduzione originale attraverso l'uso di rep()'s eache lengthargomenti (e corrispondenza parziale degli argomenti), e ricordando che 0:1è equivalente a c(0,1).

for(n in 2^(0:3))print(rep(0:1,e=n,l=16))

for(n in 2^(0:3))print(rep(c(rep(0,n),rep(1,n)),8/n))

Puoi anche tentare una traduzione della risposta J di @ Gareth, qualcosa del genere (34 byte):

t(e1071::bincombinations(4))[4:1,]

Tuttavia, utilizza una funzione che non fa parte della base R e genera una matrice che è difficile da formattare in un testo stampato esatto come nelle specifiche.

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.