Semplice programma per gatti


84

Uno dei compiti standard più comuni (specialmente quando si mettono in mostra linguaggi di programmazione esoterici) è implementare un "programma cat" : leggere tutto STDIN e stamparlo su STDOUT. Mentre questo prende il nome dall'utilità della shell Unix catè ovviamente molto meno potente di quello reale, che viene normalmente utilizzato per stampare (e concatenare) diversi file letti dal disco.

Compito

È necessario scrivere un programma completo che legge i contenuti del flusso di input standard e li scrive alla lettera nel flusso di output standard. Se e solo se la tua lingua non supporta i flussi di input e / o output standard (come inteso nella maggior parte delle lingue), puoi invece prendere questi termini per indicare il loro equivalente più vicino nella tua lingua (ad esempio JavaScript prompte alert). Questi sono gli unici forme ammissibili di I / O, poiché qualsiasi altra interfaccia cambierebbe in gran parte la natura dell'attività e renderebbe le risposte molto meno comparabili.

L'output dovrebbe contenere esattamente l'input e nient'altro . L'unica eccezione a questa regola è l'output costante dell'interprete della tua lingua che non può essere soppresso, come un saluto, codici colore ANSI o rientro. Questo vale anche per le nuove righe finali. Se l'input non contiene una nuova riga finale, anche l'output non dovrebbe includerne uno! (L'unica eccezione è se la tua lingua stampa sempre una nuova riga finale dopo l'esecuzione.)

L'output al flusso di errore standard viene ignorato, purché il flusso di output standard contenga l'output previsto. In particolare, ciò significa che il programma può terminare con un errore quando si colpisce la fine del flusso (EOF), a condizione che non inquini il flusso di output standard. Se lo fai, ti incoraggio ad aggiungere anche una versione senza errori alla tua risposta (per riferimento).

Poiché ciò è inteso come una sfida all'interno di ciascuna lingua e non tra le lingue, esistono alcune regole specifiche per la lingua:

  • Se è possibile nella tua lingua distinguere byte nulli nel flusso di input standard da EOF, il tuo programma deve supportare byte null come qualsiasi altro byte (cioè, devono essere scritti anche nel flusso di output standard).
  • Se è assolutamente possibile nella tua lingua supportare un flusso di input infinito arbitrario (ovvero se puoi iniziare a stampare byte sull'output prima di premere EOF nell'input), il tuo programma deve funzionare correttamente in questo caso. Ad esempio, yes | tr -d \\n | ./my_catdovrebbe stampare un flusso infinito di ys. Spetta a te quanto spesso stampi e svuoti il ​​flusso di output standard, ma deve essere garantito che accada dopo un periodo di tempo limitato, indipendentemente dal flusso (ciò significa, in particolare, che non puoi aspettare un carattere specifico come un avanzamento riga prima della stampa).

Aggiungi una nota alla tua risposta sul comportamento esatto relativo a byte null, flussi infiniti e output estraneo.

Regole aggiuntive

  • Non si tratta di trovare la lingua con la soluzione più breve per questo (ci sono alcuni in cui il programma vuoto fa il trucco) - si tratta di trovare la soluzione più breve in ogni lingua. Pertanto, nessuna risposta verrà contrassegnata come accettata.

  • Le iscrizioni nella maggior parte delle lingue verranno classificate in byte in una codifica preesistente appropriata, di solito (ma non necessariamente) UTF-8.

    Alcune lingue, come Cartelle , sono un po 'difficili da segnare. In caso di dubbi, si prega di chiedere su Meta .

  • Sentiti libero di usare una lingua (o versione linguistica) anche se è più recente di questa sfida. Le lingue specificamente scritte per inviare una risposta di 0 byte a questa sfida sono un gioco leale ma non particolarmente interessante.

    Si noti che deve essere presente un interprete per poter testare l'invio. È permesso (e persino incoraggiato) di scrivere questo interprete per una lingua precedentemente non implementata.

    Si noti inoltre che le lingue non devono soddisfare i nostri criteri abituali per i linguaggi di programmazione .

  • Se la tua lingua preferita è una banale variante di un'altra lingua (potenzialmente più popolare) che ha già una risposta (pensa a dialetti BASIC o SQL, shell Unix o banali derivati ​​Brainfuck come Headsecks o Unary), considera di aggiungere una nota alla risposta esistente che la stessa soluzione o molto simile è anche la più breve nell'altra lingua.

  • A meno che non siano stati annullati in precedenza, si applicano tutte le regole standard , incluso http://meta.codegolf.stackexchange.com/q/1061 .

Come nota a margine, si prega di non sottovalutare le risposte noiose (ma valide) in lingue in cui non c'è molto da golf; questi sono ancora utili a questa domanda in quanto tenta di compilare un catalogo il più completo possibile. Tuttavia, valuta principalmente le risposte nelle lingue in cui l'autore ha dovuto effettivamente sforzarsi di giocare a golf con il codice.

Catalogare

Lo snippet di stack nella parte inferiore di questo post genera il catalogo dalle risposte a) come elenco della soluzione più breve per lingua eb) come classifica generale.

Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, utilizzando il seguente modello Markdown:

## Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Se si desidera includere più numeri nell'intestazione (ad es. Perché il punteggio è la somma di due file o si desidera elencare separatamente le penalità del flag dell'interprete), assicurarsi che il punteggio effettivo sia l' ultimo numero nell'intestazione:

## Perl, 43 + 2 (-p flag) = 45 bytes

Puoi anche rendere il nome della lingua un collegamento che verrà quindi visualizzato nello snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


52
Bash, 3 byte :cat
TheDoctor

3
@TheDoctor Immagino che questo rientri nella regola "non usare un built-in che fa esattamente ciò che è necessario".
Paŭlo Ebermann,

5
@ PaŭloEbermann Non esiste una regola del genere e la scappatoia standard corrispondente non viene più accettata. (In effetti, esiste già una shrisposta utilizzando catche contiene anche una soluzione più breve utilizzando dd.)
Martin Ender

1
Se solo usasse metodi standard di input e output: ///, 0 byte .
Compagno SparklePony

1
@SparklePony Tranne che dovresti sfuggire a barre e barre rovesciate.
Martin Ender,

Risposte:


73

sed, 0


Il sedprogramma vuoto fa esattamente ciò che è richiesto qui:

$ printf "abc\ndef" | sed ''
abc
def$ 

3
Cosa succede se si scrive yes | tr -d \\n | sed ''?
BenGoldberg,

@BenGoldberg Di default sed funziona su una base per riga, quindi in questo caso continuerà ad assorbire yesi dati in un buffer di pattern fino a quando non si esaurisce la memoria. Un avvertimento suppongo ...
Digital Trauma

POSIX impone che lo spazio del modello deve avere una dimensione di almeno 8192 byte, IIRC. So che l'implementazione GNU ha uno spazio di pattern dinamico, limitato solo dalla memoria disponibile, quindi sei abbastanza sicuro su quello.
Toby Speight,

59

Ziim , 222 201 196 185 182 byte

    ↓ ↓

 ↓ ↓     ↓
 ↗ ↗↙↔↘↖ ↖
 ↓↓⤡⤢  ⤢↙
↘ ↖⤡ ↖
  ↙
  ↕↘ ↑ ↙
→↘↖↑ ↙ ↑
→↖   ↑
→↖↘ ↙
  ↑↓↑

   ⤡

Questo probabilmente non verrà visualizzato correttamente nel tuo browser, quindi ecco un diagramma del codice:

inserisci qui la descrizione dell'immagine

Non riesco a pensare a una struttura più semplice per risolvere il problema in Ziim, ma sono sicuro che il codice attuale sia ancora abbastanza giocabile.

Ziim non può gestire flussi infiniti perché è possibile stampare qualsiasi cosa alla fine del programma.

Spiegazione

Poiché Ziim ha un modello di flusso di controllo dichiarativo piuttosto unico, un algoritmo pseudocodico imperativo non lo taglierà qui. Invece, spiegherò le basi di Ziim e del presente la struttura riordinata del codice sopra (in modo grafico simile) come l'arte ASCII.

Il flusso di controllo in Ziim avviene ovunque: ogni freccia che non è puntata da un'altra freccia inizializza un "thread" che viene elaborato indipendentemente dagli altri (non proprio in parallelo, ma non ci sono garanzie in quale ordine vengano elaborati , a meno che tu non li sincronizzi tramite concatenazione). Ciascuno di questi thread contiene un elenco di cifre binarie, a partire da {0}. Ora ogni freccia nel codice è una sorta di comando che ha uno o due input e uno o due output. Il comando esatto dipende da quante frecce puntano verso di esso da quali orientamenti.

Ecco l'elenco dei comandi, dove m -> nindica che il comando accetta minput e produce noutput.

  • 1 -> 1, no-op : reindirizza semplicemente il thread.
  • 1 -> 1, invert : annulla ogni bit nel thread (e lo reindirizza anche).
  • 1 -> 1, leggi : sostituisce il valore del thread con il bit successivo di STDIN o con l'elenco vuoto se abbiamo premuto EOF.
  • 2 -> 1, concatenare : questo è l'unico modo per sincronizzare i thread. Quando un filo colpisce un lato della freccia, verrà sospeso fino a quando un altro filo non colpisce l'altro lato. A quel punto verranno concatenati in un singolo thread e continueranno l'esecuzione.
  • 2 -> 1, etichetta : questo è l'unico modo per unire diversi percorsi di esecuzione. Questo è semplicemente un no-op che ha due possibili ingressi. Quindi i thread che entrano nell '"etichetta" tramite entrambe le rotte verranno semplicemente reindirizzati nella stessa direzione.
  • 1 -> 2, split : accetta un singolo thread e invia due copie in diverse direzioni.
  • 1 -> 1, isZero? : consuma il primo bit del thread e invia il thread in una delle due direzioni a seconda che il bit fosse 0 o 1.
  • 1 -> 1, è vuoto? : consuma l'intero elenco (ovvero lo sostituisce con un elenco vuoto) e invia il thread in una delle due direzioni a seconda che l'elenco fosse già vuoto o meno.

Quindi, con questo in mente, possiamo capire una strategia generale. Usando concatenate vogliamo aggiungere ripetutamente nuovi bit a una stringa che rappresenta l'intero input. Possiamo semplicemente farlo ricollegando l'output del concatenato in uno dei suoi input (e inizializzandolo in un elenco vuoto, cancellando a {0}con isEmpty? ). La domanda è: come possiamo terminare questo processo.

Oltre ad aggiungere il bit corrente, anteponiamo anche uno 0 o 1 che indica se abbiamo raggiunto EOF. Se inviamo la nostra stringa tramite isZero? , elimineremo di nuovo quel bit, ma distinguiamo la fine dello stream, nel qual caso lasciamo semplicemente che il thread lasci il bordo della griglia (il che fa sì che Ziim stampi il contenuto del thread su STDOUT e termini il programma) .

Se abbiamo raggiunto EOF o no può essere determinato usando isEmpty? su una copia dell'input.

Ecco il diagramma che ho promesso:

              +----------------------------+   {0} --> isEmpty --> label <--+
              |                            |                    n    |      |
              v                            |                         v      |
    {0} --> label --> read --> split --> split ------------------> concat   |
                                 |                                   |      |
                           n     v     y                             |      |
 inv --> label --> concat <-- isEmpty --> concat <-- label <-- {0}   |      |
  ^        ^          |                     |          ^             |      |
  |        |          v                     v          |             |      |
 {0}       +------- split ---> label <--- split -------+             |      |
                                 |                                   |      |
                                 +-------------> concat <------------+      |
                                                   |                        |
                                              y    v                        |
                         print and terminate <-- isZero --------------------+

Alcune note su dove iniziare a leggere:

  • Il {0}nell'angolo in alto a sinistra è l'innesco iniziale che inizia il ciclo di ingresso.
  • L' {0}angolo in alto a destra viene immediatamente cancellato in un elenco vuoto e rappresenta la stringa iniziale che riempiremo gradualmente con l'input.
  • Gli altri due {0}s sono alimentati in un ciclo "produttore" (uno invertito, uno no), a darci una quantità illimitata di 0s e 1s, che abbiamo bisogno di anteporre alla stringa.

29
Come puoi anche scrivere un programma del genere senza che il tuo cervello esploda in un milione di pezzetti di tessuto.
Ashwin Gupta,

40

Esagonia , 6 byte

Questo era composto da 3 byte (vedi sotto), ma quella versione non funziona più dall'ultimo aggiornamento della lingua. Dato che non ho mai introdotto intenzionalmente l'errore utilizzato dalla versione, ho deciso di non contarlo.


Una soluzione priva di errori (ovvero una che funziona con l'interprete fisso) risulta molto più complicata. Ho avuto qualche problema a comprimerlo in una griglia 2x2, ma ho trovato una soluzione ora, anche se ho bisogno dei 7 byte completi :

<)@,;.(

Dopo lo sviluppo, otteniamo:

inserisci qui la descrizione dell'immagine

Poiché il bordo di memoria iniziale è 0, il <deflettore incondizionato devia incondizionatamente nella diagonale nord-est, dove si avvolge sul percorso grigio. Il .è un no-op. Ora ,legge un byte, lo )incrementa in modo tale che i byte validi (inclusi i byte null) siano positivi e EOF sia 0.

Quindi su EOF, l'IP passa al percorso rosso, dove @termina il programma. Ma se leggiamo ancora un byte, l'IP si sposta sul percorso verde invece è dove (decrementa il bordo sul valore originale, prima ;di stamparlo su STDOUT. L'IP ora ritorna incondizionatamente al percorso grigio, ripetendo il processo.


Dopo aver scritto uno script di forza bruta per la mia risposta a Truth Machine, l'ho impostato per trovare una soluzione a 6 byte senza errori anche per il programma cat. Sorprendentemente, ha trovato una - sì, esattamente una soluzione in tutti i possibili programmi Hexagony a 6 byte. Dopo le 50 soluzioni della macchina della verità, è stato abbastanza sorprendente. Ecco il codice:

~/;,@~

Apertura:

inserisci qui la descrizione dell'immagine

L'uso di ~(negazione unaria) invece di ()è interessante, perché a) è un no-op su zero, b) scambia i lati del ramo, c) in alcuni codici un singolo ~potrebbe essere usato due volte per annullare l'operazione con se stesso . Quindi ecco cosa sta succedendo:

La prima volta (percorso viola) che attraversiamo ~è una no-op. Il /riflette l'IP nel Nord-Ovest diagonale. Il percorso grigio ora legge un carattere e moltiplica il suo codice carattere per -1. Ciò trasforma l'EOF ( -1) in un valore di verità (positivo) e tutti i caratteri validi in valori di falsa (non positivo). Nel caso di EOF, l'IP prende il percorso rosso e il codice termina. Nel caso di un carattere valido, l'IP prende il percorso verde, dove ~annulla la negazione e ;stampa il carattere. Ripetere.


Infine, ecco la versione a 3 byte che funzionava nella versione originale interprete Hexagony.

,;&

Come la risposta Labyrinth, questo termina con un errore se il flusso di input è finito.

Dopo aver spiegato il codice, corrisponde alla seguente griglia esadecimale:

inserisci qui la descrizione dell'immagine

Non ci .sono operazioni. L'esecuzione inizia sul percorso viola.

,legge un byte, ;scrive un byte. Quindi l'esecuzione continua sulla via del salmone (ish?). Abbiamo bisogno &di reimpostare il bordo di memoria corrente a zero, in modo tale che l'IP ritorni alla riga viola quando colpisce l'angolo alla fine della seconda riga. Una volta ,colpito EOF tornerà -1, causando un errore quando ;si tenta di stamparlo.


Diagrammi generati con Timwi sorprendente s' HexagonyColorer .


2
La versione a 6 byte è molto, molto intelligente. I forzanti brutali possono essere incredibilmente fantastici.
ETHproductions

Hai un link al tuo bruto-forcer?
MD XF,

@MDXF Non tengo in giro le varie versioni, ma è sempre una modifica di questo script Ruby .
Martin Ender,

36

TeaScript , 0 byte

TeaScript è un linguaggio di golf conciso compilato in JavaScript


In un recente aggiornamento, l'input viene aggiunto implicitamente come prima proprietà.

Provalo online


In alternativa, 1 byte

x

xcontiene l'input in TeaScript. L'output è implicito


Stavo per pubblicare questo :)
Kritixi Lithos il

5
Ah, pensavo che "In alternativa" fosse un nome in lingua ...
Quelklef,

28

Brian e Chuck , 44 byte

#{<{,+?+}_+{-?>}<?
_}>?>+<<<{>?_}>>.<+<+{<{?

Inizialmente ho creato questo linguaggio per Creare un linguaggio di programmazione che sembra essere inutilizzabile . Si scopre che è un esercizio molto piacevole per risolvere semplici problemi.

Le basi: ciascuna delle due linee definisce un programma simile a Brainfuck che opera sul codice sorgente dell'altro programma: il primo programma si chiama Brian e il secondo si chiama Chuck. Solo Brian sa leggere e solo Chuck sa scrivere. Invece dei loop di Brainfuck, hai il ?controllo che passa al controllo dell'altro programma (e cambiano anche i ruoli del puntatore dell'istruzione e della testina del nastro). Un'aggiunta a Brainfuck è {e }che esegue la scansione del nastro per la prima cella diversa da zero (o l'estremità sinistra). Inoltre, _vengono sostituiti con byte null.

Anche se non penso che sia ancora ottimale, sono abbastanza contento di questa soluzione. Il mio primo tentativo è stato di 84 byte, e dopo diverse sessioni di golf con Sp3000 (e prendendo ispirazione dai suoi tentativi), sono riuscito a farlo lentamente scendere a 44, pochi byte alla volta. Soprattutto il +}+trucco geniale è stata la sua idea (vedi sotto).

Spiegazione

L'input viene letto nella prima cella del nastro di Chuck, quindi scrupolosamente copiato alla fine del nastro di Brian, dove è stampato. Copiandolo fino alla fine, possiamo salvare i byte impostando il carattere precedente su zero.

L' #è solo un sostituto, perché commutazione controllo non esegue la cella abbiamo acceso. {<{assicura che la testina del nastro sia sulla prima cella di Chuck. ,legge un byte da STDIN o -1se colpiamo EOF. Quindi lo incrementiamo con +per renderlo zero per EOF e diverso da zero altrimenti.

Supponiamo che per ora non siamo ancora all'EOF. Quindi la cella è positiva e ?passerà il controllo a Chuck. }>sposta la testina del nastro (su Brian) +sul _e ?passa il controllo a Brian.

{-ora decrementa la prima cella su Chuck. Se non è ancora zero, passiamo di nuovo il controllo a Chuck con ?. Questa volta }>sposta la testina del nastro su Brian di due celle a destra dell'ultima cella diversa da zero. Inizialmente è qui:

#{<{,+?+}_+{-?>}<?__
                   ^

Ma più avanti, avremo già alcuni personaggi lì. Ad esempio, se abbiamo già letto e stampato abc, sembrerebbe così:

#{<{,+?+}_+{-?>}<?11a11b11c__
                            ^

Dove le 1s sono in realtà 1 byte (vedremo di cosa si tratta in seguito).

Questa cella sarà sempre zero, quindi questa volta ? non cambierà il controllo. >sposta ancora un'altra cella a destra e +incrementa quella cella. Questo è il motivo per cui il primo carattere nell'input finisce tre celle a destra della ?(e ciascuna successiva tre celle più a destra).

<<<torna all'ultimo carattere in quell'elenco (o il ?se è il primo carattere) e {>torna al +nastro di Brian per ripetere il ciclo, che trasferisce lentamente la cella di input alla fine del nastro di Brian.

Una volta che la cella di input è vuota, il ?dopo {-non passa più il controllo. Quindi >}<sposta la testina del nastro su Chuck _e commuta i controlli in modo tale che venga eseguita la seconda metà di Chuck.

}>>si sposta nella cella che ora abbiamo scritto oltre la fine del nastro di Brian, che è il byte che abbiamo letto da STDIN, quindi lo stampiamo nuovamente .. Per }superare questo nuovo carattere sul nastro, è necessario colmare il divario di due byte nulli, quindi li incrementiamo a 1con <+<+(quindi è per questo che ci sono 1 byte tra i caratteri effettivi sul nastro finale). Alla fine {<{torna all'inizio del nastro di Brian e ?inizia tutto dall'inizio.

Potresti chiederti cosa succede se il carattere che leggiamo era un byte null. In tal caso la cella appena scritta sarebbe di per sé zero, ma poiché è alla fine del nastro di Brian e non ci interessa dove si trovi quella fine, possiamo semplicemente ignorarlo. Ciò significa che se l'input fosse ab\0de, il nastro di Brian finirà per apparire come:

#{<{,+?+}_+{-?>}<?11a11b1111d11e

Alla fine, una volta che abbiamo colpito EOF, la prima volta ?sul nastro di Brian sarà una no-op. A questo punto terminiamo il programma. La soluzione più semplice sarebbe quella di spostare al fine del controllo nastro e l'interruttore di Chuck, tale che le termiantes programma: >}>}<?. È qui che l'idea davvero intelligente di Sp3000 consente di risparmiare tre byte:

+trasforma la prima cella di Chuck in 1. Ciò significa che }ha un punto di partenza e trova _il mezzo nel nastro di Chuck. Invece di saltarlo, semplicemente colmiamo il divario trasformandolo in un 1con +. Ora vediamo cosa succede il resto del codice di Brian con questo Chuck modificato ...

{torna alla prima cella di Chuck come al solito, e la -trasforma in un byte null. Ciò significa che ?è una no-op. Ma ora >}<, che di solito spostava la testina del nastro al centro del nastro di Chuck, passa proprio davanti alla fine del nastro di Chuck e ?passa il controllo a Chuck, terminando il codice. È bello quando le cose vanno bene ... :)


25

Haskell, 16 byte

main=interact id

interactlegge l'input, lo passa alla funzione fornita come argomento e stampa il risultato che riceve. idè la funzione identità, ovvero restituisce immutato il suo input. Grazie alla pigrizia di Haskell interactpuò lavorare con input infiniti.


23

sh + binutils, 3 2 byte

dd

Beh, non è così ovvio. Da @ Random832

Originale:

cat

Il dolorosamente ovvio ...: D


12
Farò uno migliore: dd.
Casuale 832

Stavo per fare il gatto ... D:
ev3commander il

1
Sì, questo è fantastico e tutto ... ma 170 rappresentanti per la digitazione cat???
MD XF,

1
@MDXF che dire di chissà quanto rappresentante di un segfault? ;)
caird coinheringaahing

23

Funciton , 16 byte

╔═╗
╚╤╝

(Codificato come UTF-16 con una DBA)

Spiegazione

La casella restituisce il contenuto di STDIN. L'estremità libera lo emette.


19

Codice macchina Motorola MC14500B , 1,5 byte

Scritto in esadecimale:

18F

Scritto in binario:

0001 1000 1111

Spiegazione

1   Read from I/O pin
8   Output to I/O pin
F   Loop back to start

I codici operativi sono ciascuno a 4 bit.


1
-1 nessuna schermata, esempio o collegamento Provalo online: P (jk)
MD XF

2
+1. L'unico modo in cui riesco a pensare di ottimizzare ulteriormente sarebbe quello di saldare il pin di input al pin di output ed estrarre il chip dal suo socket: P
Wossname

16

Mornington Crescent , 41 byte

Take Northern Line to Mornington Crescent

Non ho idea se Mornington Crescent è in grado di gestire byte null e tutti gli input vengono letti prima dell'avvio del programma, poiché questa è la natura della lingua.


15

Brainfuck, 5 byte

,[.,]

Equivalente allo pseudocodice:

x = getchar()
while x != EOF:
    putchar(x)
    x = getchar()

Gestisce flussi infiniti, ma tratta byte nulli come EOF. Il fatto che BF sia in grado di gestire correttamente byte nulli varia da una implementazione all'altra, ma questo presuppone l'approccio più comune.


1
DARN! Mi hai battuto per 5 minuti!
Kirbyfan64sos,

Se il primo carattere è NULL, questo non funzionerà correttamente. Quindi dovrebbe essere +[,.]giusto?
Shelvacu,

6
@Shel Questo sta usando 0x00 come byte EOF. Se il primo personaggio è EOF, non stampa nulla, funzionando come previsto.
Mego

2
"pseudocodice" oh andiamo che è chiaramente solo senza parentesi, senza punto e virgola C: P
MD XF

14

Labirinto , 2 byte

,.

Se il flusso è finito, questo terminerà con un errore, ma tutto l'output prodotto dall'errore va a STDERR, quindi il flusso di output standard è corretto.

Come in Brainfuck ,legge un byte (spingendolo nello stack principale di Labyrinth) e .scrive un byte (estraendolo dallo stack principale di Labyrinth).

La ragione per cui questo loop è che entrambi ,e .sono "vicoli ciechi" nel labirinto (molto banale) rappresentato dal codice sorgente, in modo tale che il puntatore dell'istruzione si giri semplicemente sul posto e torni indietro all'altro comando.

Quando premiamo EOF ,spinge -1invece e .genera un errore perché -1non è un codice carattere valido. Questo potrebbe effettivamente cambiare in futuro, ma non l'ho ancora deciso.


Per riferimento, possiamo risolverlo senza errori in 6 byte come segue

,)@
.(

Qui, gli )incrementi del byte che leggiamo, che danno 0a EOF e qualcosa di positivo altrimenti. Se il valore è 0, l'IP si sposta direttamente, premendo il tasto @che termina il programma. Se il valore era positivo, l'IP prenderà invece una svolta a destra verso il (quale diminuisce la parte superiore dello stack al suo valore originale. L'IP è ora in un angolo e continuerà semplicemente a girare a destra, a stampare con ., a leggere un nuovo byte con ., prima di colpire )nuovamente il fork .


13

C, 40 byte

main(i){while(i=~getchar())putchar(~i);}

main () {while (255-putchar (getchar ()));} è più corto di un paio di byte.
Alchymist,

1
Purtroppo, questo si chiude prematuramente su byte 0xFF e aggiunge un byte 0xFF all'input se non lo contiene.
Dennis,

Che dire dei seguenti, 36 byte: main () {for (;; putchar (getchar ()));};
Johan du Toit,

@ user2943932 Quando colpisce EOF, getcharrestituisce -1 , quindi il tuo codice stamperà un flusso infinito di 0xFF byte dopo l'input (finito).
Dennis,

12

> <> , 7 byte

i:0(?;o

Provalo qui . Spiegazione:

i:0(?;o
i        Take a character from input, pushing -1 if the input is empty
 :0(     Check if the input is less than 0, pushing 1 if true, 0 if false
    ?;   Pop a value of the top of the stack, ending the program if the value is non-zero
      o  Otherwise, output then loop around to the left and repeat

Se vuoi che continui fino a quando non gli dai più input, sostituisci ;con !.


Oh, amico, speravo di pubblicare la risposta <<> ...: P (+1!)
El'endia Starman,

1
io(2 byte) fa lo stesso, ma si arresta something smells fishy...in modo anomalo e scrive su STDERR al termine dell'esecuzione, il che è consentito.
Lynn,

@Mauris l'interprete online emette solo byte null invece di terminare con un errore.
DanTheMan,

11

Assemblaggio X86, 70 byte

Smontaggio con objdump:

00000000 <.data>:
   0:   66 83 ec 01             sub    sp,0x1
   4:   66 b8 03 00             mov    ax,0x3
   8:   00 00                   add    BYTE PTR [eax],al
   a:   66 31 db                xor    bx,bx
   d:   66 67 8d 4c 24          lea    cx,[si+0x24]
  12:   ff 66 ba                jmp    DWORD PTR [esi-0x46]
  15:   01 00                   add    DWORD PTR [eax],eax
  17:   00 00                   add    BYTE PTR [eax],al
  19:   cd 80                   int    0x80
  1b:   66 48                   dec    ax
  1d:   78 1c                   js     0x3b
  1f:   66 b8 04 00             mov    ax,0x4
  23:   00 00                   add    BYTE PTR [eax],al
  25:   66 bb 01 00             mov    bx,0x1
  29:   00 00                   add    BYTE PTR [eax],al
  2b:   66 67 8d 4c 24          lea    cx,[si+0x24]
  30:   ff 66 ba                jmp    DWORD PTR [esi-0x46]
  33:   01 00                   add    DWORD PTR [eax],eax
  35:   00 00                   add    BYTE PTR [eax],al
  37:   cd 80                   int    0x80
  39:   eb c9                   jmp    0x4
  3b:   66 b8 01 00             mov    ax,0x1
  3f:   00 00                   add    BYTE PTR [eax],al
  41:   66 31 db                xor    bx,bx
  44:   cd 80                   int    0x80

La fonte:

sub esp, 1
t:
mov eax,3
xor ebx,ebx
lea ecx,[esp-1]
mov edx,1
int 0x80
dec eax
js e
mov eax,4
mov ebx,1
lea ecx,[esp-1]
mov edx,1
int 0x80
jmp t
e:
mov eax,1
xor ebx,ebx
int 0x80

1
Quindi, objdumplo hai smontato come codice a 32 bit, mentre sembra che tu abbia compilato come codice a 16 bit. Cosa credere? Dal momento che usi int 0x80, suppongo sia pensato per Linux, ma perché compilarlo come 16-bit allora?
Ruslan,

@Ruslan Non avevo nemmeno realizzato che fosse compilato in 16 bit ...
kirbyfan64sos

11

Lambda universale , 1 byte

!

Un programma Universal Lambda è una codifica di un termine lambda in binario, suddiviso in blocchi di 8 bit, riempiendo blocchi incompleti con qualsiasi bit, convertiti in un flusso di byte.

I bit sono tradotti in un termine lambda come segue:

  • 00 introduce un'astrazione lambda.
  • 01 rappresenta un'applicazione di due termini successivi.
  • 111..10, Con n ripetizioni della punta 1, si riferisce alla variabile del n ° genitore lambda; cioè è un indice di De Bruijn in unario.

Con questa conversione, 0010è la funzione di identità λa.a, il che significa che qualsiasi programma a byte singolo del modulo 0010xxxxè un catprogramma.


1
Ma !è 0x21, no 0x4_?
wchargin,

Fisso. --------
Lynn,

10

PowerShell, 88 41 30 byte

$input;write-host(read-host)-n

EDIT - ho dimenticato che posso usare la $inputvariabile automatica per l'input della pipeline ... EDIT2 - non è necessario verificare l'esistenza di$input

Sì, quindi ... STDIN in PowerShell è ... strano, dovremmo dire. Partendo dal presupposto che dobbiamo accettare input da tutti i tipi di STDIN, questa è una possibile risposta a questo catalogo e sono sicuro che ce ne sono altri. 1

Tuttavia, l'input della pipeline in PowerShell non funziona come si potrebbe pensare. Poiché il piping in PowerShell è una funzione del linguaggio e non una funzione dell'ambiente / shell (e PowerShell non è in realtà solo un linguaggio), ci sono alcune stranezze nel comportamento.

Per cominciare, e più rilevante per questa voce, la pipe non viene valutata istantaneamente (la maggior parte delle volte). Il significato, se abbiamo command1 | command2 | command3nella nostra shell, command2non prenderà input o avvierà l'elaborazione fino al command1completamento ... a meno che non incapsuli il tuo command1con un ForEach-Object... che è diverso da ForEach. (anche se ForEachè un alias per ForEach-Object, ma questo è un problema separato, dal momento che sto parlando ForEachcome l'affermazione, non alias)

Ciò significherebbe che qualcosa del genere yes | .\simple-cat-program.ps1(anche se in yesrealtà non esiste, ma qualunque cosa) non funzionerebbe perché yesnon si completerebbe mai. Se potessimo farlo, ForEach-Object -InputObject(yes) | .\simple-cat-program.ps1dovrebbe (in teoria) funzionare.

Conoscere ForEach e ForEach-Object su Microsoft "Hey, Scripting Guy!" blog.

Quindi, tutti quei paragrafi spiegano perché if($input){$input}esiste. Prendiamo un parametro di input appositamente creato automaticamente se è presente l'input della pipeline, testiamo se esiste e, in tal caso, lo output.

Quindi, prendiamo l'input dall'utente (read-host)tramite quello che è essenzialmente un flusso STDIN separato, e write-hostlo usciamo con il -nflag (abbreviazione di -NoNewLine). Si noti che ciò non supporta l'inserimento di lunghezza arbitraria, poiché read-hostverrà completato solo quando viene inserito un avanzamento riga (tecnicamente quando l'utente preme "Invio", ma funzionalmente equivalente).

Uff.

1 Ma ci sono altre opzioni:

Ad esempio, se ci occupassimo solo dell'input della pipeline e non avessimo bisogno di un programma completo, potreste fare qualcosa del genere | $_che produrrebbe semplicemente qualsiasi input. (In generale, questo è in qualche modo ridondante, dal momento che PowerShell ha un output implicito di cose "lasciate indietro" dopo i calcoli, ma questo è un lato.)

Se ci occupiamo solo dell'input dell'utente interattivo, potremmo usare solo write-host(read-host)-n.

Inoltre, questa funzione ha la coincidenza caratteristica di accettare input di comandi, ad esempio .\simple-cat-program.ps1 "test"avrebbero popolato (e quindi output) la $avariabile.


non dimenticare i tuoi alias incorporati!
Chad Baxter,

10

Cubix , 6 5 byte

Ora gestisce byte nulli!

@_i?o

Cubix è un esolang bidimensionale basato su stack. Cubix è diverso dalle altre lingue 2D in quanto il codice sorgente è racchiuso all'esterno di un cubo.

Provalo online! Nota: c'è un ritardo di 50 ms tra le iterazioni.

Spiegazione

La prima cosa che fa l'interprete è capire il cubo più piccolo su cui si adatterà il codice. In questo caso, la lunghezza del bordo è 1. Quindi il codice viene riempito con nessuna operazione .fino a quando tutti e sei i lati sono riempiti. Lo spazio bianco viene rimosso prima dell'elaborazione, quindi questo codice è identico al precedente:

  @
_ i ? o
  .

Ora il codice è in esecuzione. L'IP (puntatore alle istruzioni) inizia sulla faccia all'estrema sinistra, puntando verso est.

Il primo carattere che l'IP incontra è _, che è un mirror che gira l'IP se è rivolto a nord o sud; è attualmente rivolto a est, quindi questo non fa nulla. Il prossimo è i, che immette un byte da STDIN. ?trasforma l'IP a sinistra se l'elemento in alto è negativo o a destra se è positivo. Ci sono tre possibili percorsi qui:

  • Se il byte immesso è -1 (EOF), l'IP gira a sinistra e colpisce @, il che termina il programma.
  • Se il byte immesso è 0 (byte null), l'IP continua semplicemente dritto, emettendo il byte con o.
  • Altrimenti, l'IP gira a destra, attraversa la faccia inferiore e colpisce lo specchio _. Questo lo gira, rimandandolo a ?, che lo gira di nuovo a destra e genera il byte.

Penso che questo programma sia ottimale. Prima che Cubix potesse gestire byte null (EOF era 0, non -1), questo programma funzionava per tutto tranne che per i byte null:

.i!@o

Ho scritto un bruto-forcer per trovare tutti i programmi cat a 5 byte. Anche se ci vogliono circa 5 minuti per finire, l'ultima versione ha trovato 5 programmi:

@_i?o   (works as expected)
@i?o_   (works in exactly the same way as the above)
iW?@o   (works as expected)
?i^o@   (false positive; prints U+FFFF forever on empty input)
?iWo@   (works as expected)

Per favore, non modificare una dozzina di post contemporaneamente. Stai inondando la prima pagina. 3 alla volta non è un problema, ma se devi fare di più, esegui le modifiche in piccoli lotti ogni 12 ore circa.
Martin Ender,

@MartinEnder Siamo spiacenti, l'ho appena notato. Li distaccerò in futuro.
ETHproductions

9

Vitsy, 2 byte

ZZ

zottiene tutto lo stack di input e lo spinge nello stack di programma attivo. Zstampa tutto lo stack attivo su STDOUT.

Metodo alternativo:

I \ Il \ O
I \ Ripeti il ​​carattere successivo per la lunghezza dello stack di input.
  Prendo un oggetto dall'input.
   l \ Ripeti il ​​carattere successivo per la lunghezza dello stack del programma attualmente attivo.
     O Emette l'elemento in cima alla pila come personaggio.

2
^ _ ^ Avere comunque un +1! :)
El'endia Starman,

Peccato voti, il mio preferito!
Addison Crump,

Perché i downvotes? Questa sembra essere una voce perfettamente valida
Conor O'Brien,

1
Si è valida per tutte le specifiche.
Addison Crump,

9

MarioLANG , 11 byte

,<
."
>!
=#

Non sono del tutto sicuro che sia ottimale, ma è il più corto che ho trovato.

Questo supporta flussi infiniti e terminerà con un errore al raggiungimento dell'EOF (almeno l'implementazione del riferimento Ruby lo fa).

C'è un'altra versione di questo che trasforma Mario in un ninja che può fare doppio salto:

,<
.^
>^
==

In entrambi i casi, Mario inizia a cadere nella colonna di sinistra, dove ,legge un byte e .scrive un byte (che genera un errore su EOF perché ,non restituisce un carattere valido). >assicura che Mario cammini a destra ( =è solo un terreno su cui camminare). Quindi si alza, tramite un doppio salto con ^o tramite un ascensore (la "e la #coppia) prima che gli <dica di tornare alla colonna di sinistra.


8

rs , 0 byte


Sul serio. rs stampa qualunque cosa ottenga se lo script dato è completamente vuoto.


7

GolfScript, 3 byte

:n;

Il programma vuoto fa eco all'input standard. La lingua non può possibilmente gestire flussi infiniti. Tuttavia, aggiunge una nuova riga, come menzionato da @Dennis. Lo fa avvolgendo l'intero stack in un array e chiamando puts, che è definito come print n print, dove nè una nuova riga. Tuttavia, possiamo ridefinire nper essere STDIN e quindi svuotare lo stack, che è esattamente ciò che :n;fa.


7

Auto a metà rotta in traffico pesante , 9 + 3 = 12 byte

#<
o^<
 v

Half-Broken Car in Heavy Traffic (HBCHT) accetta input come argomenta la riga di comando, quindi corri come

py -3 hbcht cat.hbc -s "candy corn"

Si noti che +3 è per il -sflag, che viene emesso come caratteri. Inoltre, HBCHT non sembra gestire NUL, poiché tutti gli zero vengono eliminati dall'output (ad esempio, 97 0 98viene emesso come due caratteri ab).

Spiegazione

In HBCHT, la tua auto parte da oe il tuo obiettivo è l'uscita #. ^>v<dirigere il movimento dell'auto, modificando contemporaneamente un nastro simile a BF ( ^>v<tradurre in +>-<). Tuttavia, come suggerisce il nome della lingua, la tua auto può solo girare a destra - qualsiasi tentativo di girare a sinistra viene ignorato completamente (compresi i loro effetti di memoria). Nota che questo è solo per la svolta: la tua auto è perfettamente in grado di avanzare / invertire la direzione.

Altre parti interessanti di HBCHT sono che la direzione iniziale della tua auto è randomizzata e la griglia è toroidale. Quindi abbiamo solo bisogno della macchina per arrivare all'uscita senza modificare il nastro per tutte e quattro le direzioni iniziali:

  • Su e giù sono semplici, dirigendosi direttamente verso l'uscita.

  • A sinistra, eseguiamo, eseguiamo <e incrementiamo con ^. Non possiamo svoltare a sinistra al prossimo, <quindi andiamo a capo e diminuiamo con v, annullando l'incremento precedente. Dato che ora stiamo andando verso il basso, possiamo svoltare a destra <all'uscita e, dopo aver spostato il puntatore due volte e senza modificare i valori di cella.

  • Per la destra, facciamo la stessa cosa di sinistra ma saltiamo la prima ^poiché non possiamo girare a sinistra.


Modifica : si scopre che l'interprete HBCHT consente di eseguire solo un singolo percorso tramite un flag della riga di comando, ad es

py -3 hbcht -d left cat.hbc

Tuttavia, non solo la bandiera è troppo costosa per questa particolare domanda (almeno 5 byte per " -d u"), ma sembra che tutti i percorsi debbano essere ancora in grado di arrivare all'uscita per l'esecuzione del codice.


7

Minkolang , 5 byte

od?.O

Provalo qui.

Spiegazione

olegge un carattere dall'input e inserisce il suo codice ASCII nello stack ( 0se l'input è vuoto). dquindi duplica la parte superiore dello stack (il personaggio che è stato appena letto). ?è un trampolino condizionale, che non salta la prossima istruzione della parte superiore dello stack 0. Se l'ingresso era vuoto, allora .non viene saltato e il programma si interrompe. Altrimenti, Ogenera la parte superiore dello stack come personaggio. La natura toroidale di Minkolang significa che questo si snoda all'inizio.


2
Grar! Hai battuto la mia lingua! INACCETTABILE! +1
Addison Crump,

7

INTERCALL , 133 byte

wat

INTERCALL IS A ANTIGOLFING LANGUAGE
SO THIS HEADER IS HERE TO PREVENT GOLFING IN INTERCALL
THE PROGRAM STARTS HERE:
READ
PRINT
GOTO I

Sembra che qualcuno abbia davvero giocato a golf in un linguaggio puramente anti-golf ... 133-116 = 17
Erik the Outgolfer

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Poiché il programma cat è piuttosto semplice, non è questo il caso di tutti i programmi ... codegolf.stackexchange.com/a/82748/53745
TuxCrafting

La persona che ha creato la lingua intendeva usare numeri romani, ma se fosse il caso di stampare 500(non ne sono sicuro), sarebbe PRINT Dgiusto? (esclusa l'intestazione)
Erik the Outgolfer,

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ No, INTERCALL può solo stampare caratteri ASCII e usare una pila, quindi ad esempio per stampare il carattere con valore ASCII 20 il codice è PUSH XX<newline>PRINTo PUSH XX AND PRINT. Oh e io sono il creatore di INTERCALL
TuxCrafting il

7

V , 0 byte

Provalo online!

L'idea di "memoria" di V è solo una gigantesca schiera di personaggi 2D. Prima di eseguire qualsiasi programma, tutti gli input caricati in questo array (noto come "The Buffer"). Quindi, alla fine di qualsiasi programma, viene stampato tutto il testo nel buffer.

In altre parole, il programma vuoto è un programma cat.


6

Snowman 1.0.2 , 15 caratteri

(:vGsP10wRsp;bD

Tratto direttamente dalla examplesdirectory di Snowman . Legge una riga, stampa una riga, legge una riga, stampa una riga ...

Si noti che a causa di un dettaglio dell'implementazione, quando STDIN è vuoto, vgrestituirà la stessa cosa che farebbe per una riga vuota. Pertanto, ciò stamperà ripetutamente nuove righe in un ciclo infinito una volta chiuso STDIN. Questo potrebbe essere risolto in una versione futura.

Spiegazione del codice:

(        // set two variables (a and f) to active—this is all we need
:...;bD  // a "do-loop" which continues looping as long as its "return value"
         // is truthy
  vGsP   // read a line, print the line
  10wRsp // print a newline—"print" is called in nonconsuming mode; therefore,
         // that same newline will actually end up being the "return value" from
         // the do-loop, causing it to loop infinitely


5

Fissione , 4 byte

R?J!

Non è carino quando batti i programmi di esempio nel repository della lingua? :) Per riferimento, ha la soluzione a 7 byte

R?J0;0!

Spiegazione

Quindi, Rinizia il flusso di controllo con un atomo a destra. ?legge un personaggio di STDIN nella massa dell'atomo. Finché stiamo leggendo personaggi, l'energia rimane zero, quindi l' Jump è una no-op e! stampa il personaggio. L'atomo ritorna all'inizio ( Rora è un no-op) e ripete l'intero processo.

Quando colpiamo EOF, ?imposteremo l'energia dell'atomo su 1, quindi l' Jump salterà ora il comando di stampa. Ma quando un atomo colpisce ? dopo EOF è già stato restituito, distruggerà invece l'atomo, che termina il programma.

(La soluzione dell'autore del linguaggio utilizza un esplicito ;per terminare il programma, che 0altrimenti viene ignorato con due portali).


5

Shtriped , 20 byte

e )
"
 r )
 s )
 "
"

Ciò dimostra sfacciatamente che quasi ogni stringa ASCII stampabile è un identificatore valido in Shtriped.

Come funziona:

e )   \ declares a variable named )
"     \ defines a function with 0 arguments named "
 r )  \ gets a line of string input, saving it to )
 s )  \ prints ) as a string
 "    \ recursively calls ", effectively looping forever
"     \ calls " from the main scope to get things started

Non esiste un modo reale per rilevare EOF, quindi questo scorre per sempre come la risposta di Python .

Puoi farlo fermare facilmente quando viene data una riga vuota (30 byte):

e )
"
 r )
 d ) \ tries to decrement ), if it was the empty string, aka 0, it can't, so 0 is returned all the way up
 i ) \ increment ) to put it back to normal after possibly decrementing
 s )
 "
"

Si noti che I / O Shtriped supporta solo ASCII stampabili , schede, avanzamenti riga, ritorni a capo, schede verticali e feed modulo (100 caratteri in totale). Questo perché internamente, le stringhe sono rappresentate come numeri interi di precisione arbitraria non negativa e deve esserci un alfabeto finito di caratteri per poter codificare tutte le stringhe.

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.