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.