Generazione di file bitmap PBM da testo ASCII


19

Il formato PBM (Portable BitMap) è un formato bitmap in bianco e nero ASCII molto semplice.

Ecco un esempio per la lettera 'J' (copiata e incollata dal link di Wikipedia):

P1
# Questa è una bitmap di esempio della lettera "J"
6 10
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
1 0 0 0 1 0
0 1 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0

È tempo di creare un piccolo strumento per generare file in questo piccolo formato elegante!

Il tuo obiettivo è quello di scrivere il programma più breve (in qualsiasi lingua) conforme alle seguenti regole:

  1. Il tuo programma prende una stringa da stdin (ad esempio CODEGOLF.STACKEXCHANGE.COM!)
  2. Genera un file PBM con una rappresentazione bitmap (leggibile) della stringa.
  3. Ogni personaggio è costruito come una griglia 8x8.
  4. È necessario supportare i caratteri [AZ] (tutto maiuscolo), lo spazio, un punto ('.') E un punto esclamativo ('!').
  5. Non sono ammesse librerie esterne (sicuramente nessuna relativa a PBM)!
  6. Il set di caratteri utilizzato non deve essere semplicemente esterno al programma. Parte della sfida è memorizzare i personaggi in modo efficiente ...

La verifica della validità del formato PBM può essere eseguita con GIMP (o altri). Mostra input e output di esempio!

Alla soluzione più breve verranno assegnati i punti di risposta il 31-01-2012.

Divertiti a giocare a golf!

PS: ho aggiunto un premio (in percentuale una parte enorme della mia reputazione di codegolf) per (si spera) attirare più concorrenti.


Con "la sua rappresentazione bitmap" intendi una rappresentazione del personaggio che è vicina a qualcosa che assomiglia alle lettere? Come chiudere? Sarebbe permesso qualcosa come una rappresentazione bitmap di un codice binario o del codice braille o morse?
Howard,

@Howard: l'idea è quella di generare un'immagine pbm che contenga il testo di input originale in formato 'rendering' (bitmap) ma comunque leggibile dall'uomo ( lettersin altre parole). Non diversamente dall'esempio collegato a.
ChristopheD,

Ho aggiunto il tag kolmogorov-complessità perché la maggior parte del programma sarà composta da 30 bitmap.
Peter Taylor,

@Peter Taylor: buon punto, grazie!
ChristopheD,

Sento che avremo un lungo e doloroso dibattito su ciò che costituisce una "biblioteca esterna".
JB

Risposte:


9

GolfScript, 133 byte

Questo si basa sulla mia soluzione Perl a 164 byte e utilizza lo stesso font da 4 per 5 pixel. Ancora una volta, darò prima la versione leggibile:

{91,65>"!. "+?}%:s"P4"\,8*8'FONT DATA HERE'{16base}%[3]/{:p;{[p=0]0=}s%}%]n*

Qui, FONT DATA HEREsta per 71 byte di dati di font compressi binari. La codifica è leggermente diversa rispetto alla versione Perl: invece di dividere la stringa compressa su spazi bianchi, la esplogo prima e poi la divido sul nibble 3(scelto perché capita che non si verifichi in nessun punto del font).

Dato che i dati dei caratteri nello script reale contengono caratteri non stampabili, li do come un dump esadecimale di seguito. Utilizzare xxd -rper trasformare il dump esadecimale in codice GolfScript eseguibile:

0000000: 7b39 312c 3635 3e22 212e 2022 2b3f 7d25  {91,65>"!. "+?}%
0000010: 3a73 2250 3422 5c2c 382a 3827 36e6 eff6  :s"P4"\,8*8'6...
0000020: 9219 8996 e6e7 7959 95f4 3999 9888 921a  ......yY..9.....
0000030: 8fd9 9998 2959 9514 3fe8 9eeb f21c 89b9  ....)Y..?.......
0000040: e9e6 2959 6564 3999 9889 929a 8999 8ba1  ..)Yed9.........
0000050: 295f 9283 9e6e f869 269f 9968 79e2 6299  )_...n.i&..hy.b.
0000060: 2f48 3327 7b31 3662 6173 657d 255b 335d  /H3'{16base}%[3]
0000070: 2f7b 3a70 3b7b 5b70 3d30 5d30 3d7d 7325  /{:p;{[p=0]0=}s%
0000080: 7d25 5d6e 2a                             }%]n*

A differenza dello script Perl, questo codice stampa caratteri al di fuori del set A- Z, !, ., spacecome piccoli scarabocchi buffi. Sostituire gli squiggles con spazi vuoti costerebbe 2 caratteri extra; rimuoverli del tutto costerebbe 4.

Questo è il mio primo programma GolfScript in assoluto, quindi non sarei sorpreso se ci fosse ancora spazio per l'ottimizzazione. Ecco come funziona:

  • {91,65>"!. "+?}%:smappe i caratteri di input validi ( A- Z, !, ., space) ai numeri 0 - 28 e assegna il risultato s. Qualsiasi carattere al di fuori del set valido viene mappato su -1, che è ciò che produce gli squiggles quando viene stampato.

  • "P4"\,8*8spinge i valori "P4", 8 volte la lunghezza dell'input e 8 sullo stack. Se stampati alla fine, questi formano l'intestazione PBM.

  • {16base}%[3]/prende la stringa precedente di dati font, divide ogni byte in due nibble e divide il risultato in blocchi delimitati dal valore 3. {:p;{[p=0]0=}s%}%quindi esegue il loop su questi blocchi, assegnando prima ciascun blocco alla variabile pe quindi eseguendo il ciclo sulla stringa di input rimappata s, sostituendo ciascun carattere con il valore dell'offset corrispondente in p. Il costrutto dall'aspetto divertente [p=0]0=fa lo stesso di p=, tranne per il fatto che restituisce 0 per tutti gli offset oltre la fine di p; Non mi piace davvero, ma non sono stato in grado di trovare un modo più breve per gestirlo.

  • Infine, ]n*prende tutto nello stack (i tre valori di intestazione e l'array di dati di immagine) e li unisce con le nuove righe per la stampa.


Davvero breve (secondo qualsiasi metrica). Bello!
ChristopheD,

12

Perl, 164 byte, nessuna compressione zlib / gzip

Dopo aver dormito sul problema, sono riuscito a trovare una soluzione molto più breve della mia prima. Il trucco è sfruttare una piccola lacuna nelle regole: i personaggi devono adattarsi a 8 per 8 pixel ciascuno, ma nulla dice che devono riempire tutto quello spazio. Quindi ho disegnato il mio font 4 per 5 pixel, permettendomi di impacchettare due caratteri in 5 byte.

L'output è simile al seguente:

"CIAO MONDO!" (ridimensionato x 4)

    "OH! UNA VOLPE RAPIDA MARRONE SALTA SUL CANE PIÙ BIONDO." (Misura originale)

Prima di fornire il codice effettivo con i dati dei caratteri incorporati, fammi mostrare una versione decodificata:

y/A-Z!./\0-\033/ for @a = <> =~ /./g;
say "P4 " . 8*@a . " 8";
for $p (qw'PACKED FONT DATA') {
    print chr vec $p, ord, 4 for @a;
}

Nel codice effettivo, il PACKED FONT DATAviene sostituito da una stringa binaria composta da otto righe delimitate da spazi bianchi (quattro righe da 14 byte e una da 13 byte, più tre byte nulli singoli per le righe vuote). Ho progettato deliberatamente il mio carattere in modo che i dati compressi non contengano spazi bianchi, virgolette singole o barre rovesciate, in modo che possano essere codificatiqw'...' .

Poiché la stringa di caratteri impacchettata contiene caratteri non stampabili, ho fornito lo script effettivo come dump esadecimale. Utilizzare xxd -rper trasformarlo in codice Perl eseguibile:

0000000: 792f 412d 5a21 2e2f 002d 1b2f 666f 7240  y/A-Z!./.-./for@
0000010: 613d 3c3e 3d7e 2f2e 2f67 3b73 6179 2250  a=<>=~/./g;say"P
0000020: 3420 222e 382a 4061 2e22 2038 223b 666f  4 ".8*@a." 8";fo
0000030: 7224 7028 7177 2700 20e6 e6ff 9612 8999  r$p(qw'. .......
0000040: e6e6 7759 99f5 0420 9999 8898 128a df99  ..wY... ........
0000050: 9928 5999 1504 20ef 98ee fb12 8cb9 e9e9  .(Y... .........
0000060: 2659 6965 0420 9999 8899 928a 9989 ab21  &Yie. .........!
0000070: 599f 8220 e9e6 8f96 62f9 9986 972e 2699  Y.. ....b.....&.
0000080: f284 2000 2000 2729 7b70 7269 6e74 2063  .. . .'){print c
0000090: 6872 2076 6563 2470 2c6f 7264 2c34 666f  hr vec$p,ord,4fo
00000a0: 7240 617d                                r@a}

Ecco come funziona:

  • La prima riga (nella versione de-golfed) legge una singola linea di ingresso, si divide in un array di caratteri (convenientemente omettendo ogni newline finale) e mappa le lettere Aper Zei caratteri !e .ai codici di carattere da 0 a 28, che normalmente corrispondono a caratteri di controllo non stampabili in ASCII / Unicode. (Un effetto secondario di questo è che qualsiasi scheda nell'input viene stampata come Js.) Il carattere spazio viene lasciato non mappato, poiché il loop di output trasforma comunque qualsiasi codice sopra 28 in spazi vuoti.

  • La seconda riga stampa solo l'intestazione PBM. Utilizza la sayfunzione Perl 5.10 , quindi è necessario eseguire questo script perl -M5.010affinché funzioni.

  • Il ciclo di output prende un elenco delimitato da spazi vuoti di righe di immagini impaccate e le assegna $pa turno. (Ho progettato il carattere in modo che i dati compressi non contengano spazi bianchi o 'caratteri.) Quindi passa in rassegna i caratteri di input @a, usando il veccomando Perl per estrarre il nibble a 4 bit corrispondente al codice carattere mappato dalla riga dell'immagine, lo inserisce in un byte a 8 bit e lo stampa.


Vecchia risposta, 268 byte:

Questo è un primo tentativo veloce e sporco. Ho rubato il carattere di PleaseStand e l'ho compresso insieme al mio codice sorgente. Poiché lo script risultante è per lo più non stampabile, ecco un hexdump; usare xxd -rper trasformarlo in codice Perl eseguibile:

0000000: 7573 6520 436f 6d70 7265 7373 275a 6c69  use Compress'Zli
0000010: 623b 6576 616c 2075 6e63 6f6d 7072 6573  b;eval uncompres
0000020: 7320 2778 da85 d03d 4b03 4118 85d1 452c  s 'x...=K.A...E,
0000030: b69c 72cb 7519 4894 552c 2c02 3319 ee5c  ..r.u.H.U,,.3..\
0000040: d7b8 5a89 6093 4634 7e82 c490 6c91 8597  ..Z.`.F4~...l...
0000050: 80fe 7267 d660 23ae e52d 0e0f dcd6 f8c3  ..rg.`#..-......
0000060: e9d1 5e6e ccec a15c ddb5 c5d5 495e 94a3  ..^n...\....I^..
0000070: 83b7 c7f9 73f3 5216 f9a8 787a 5fea 666c  ....s.R...xz_.fl
0000080: 9dd1 b763 dd98 76f8 2df6 0799 5811 7144  ...c..v.-...X.qD
0000090: 4acc ee9d b8b0 c90f 7e4a 8264 6016 cbd7  J.......~J.d`...
00000a0: 79f3 1b91 047c 4055 409e 9e54 1dda ed41  y....|@U@..T...A
00000b0: 9a20 8080 6adc 5c47 8488 7495 f621 01d7  . ..j.\G..t..!..
00000c0: 6b6c 902e b6c8 2a6a 6643 f56f e99c 115d  kl....*jfC.o...]
00000d0: 5c7a f1b2 13d0 3453 790f da74 c813 751d  \z....4Sy..t..u.
00000e0: 11ce d821 ad90 247f 2292 5b54 c14f 3c4e  ...!..$.".[T.O<N
00000f0: 49c5 4c53 a1a7 c478 391c 714c f113 0747  I.LS...x9.qL...G
0000100: ab6c 4482 9fd2 177a 5677 6327            .lD....zVwc'

Il codice Perl decompresso è costituito dal seguente preambolo:

y;A-Z.! ;;cd,say"P4 ",8*length," 8"for$t=<>

seguito da otto ripetizioni del seguente codice:

;$_=$t;y(A-Z.! )'BITMAP DATA HERE';print

con BITMAP DATA HEREsostituito con 29 byte che codificano una riga del carattere.


La nuova soluzione è estremamente piacevole. Non avrei mai immaginato che ciò potesse essere fatto in 165 caratteri.
ChristopheD,

6

8086 Codice macchina

190 byte (122 byte tramite BIOS)

Ecco il file .COM WinXP / MSDos con codifica Base64:

M8COwCaKDoUEitEmxD4MAaCAAP7IfliK8MHgA7cK9ve9egEAZ
vy0APb3AUb6iMi0APb3AUb+x0YACg2DxQK+ggCK7qz24YvYJo
ohswjQ5LAwFACIRgBF/st18v7NdeRH/sp10sZGACS6cAG0Cc0
hw1AxCg0wMDAgMDA=

(Usa qualcosa del genere ) per decodificare il testo e salvarlo come "pbm.com". Quindi, al prompt dei comandi, digitare:

pbm testo da codificare> outputfilename.pbm

Ho provato questo sulla mia macchina WinXP usando sia il prompt dei comandi standard che DosBox V0.74.

AGGIORNARE

Questa versione ha 190 byte e utilizza il carattere minuscolo di Ilmari Karonen (qui non è possibile accedere al BIOS!): -

voAArf7Iflq7YwG/vgG6Cg20Bfbk9vIAZfsy5PbyAUX5Vqw48HQoLEFzCDQG/sAMGSQfM8
nQ6NfA0QPS6IjEsQSwJtDsENCq4vewMKrr04DDEF6A+7N1ycYFJLqzAbQJzSHDdnb/loIZ
mXZ2flmZ9QAAIJmZEZGCFb+ZmSFZmYUPDy9/kXf9ghPZeXkmWWllAAAgmZkRmZIVmRldKF
mfEgAAAHl2H5Zi+ZkWnicmmfIAICBQMQoNMDAwIDUKDQ==

Soluzione estremamente piacevole. Al momento questo è il contendente per la taglia che sarà assegnata in circa 20 ore. Molto bene!
ChristopheD,

Puoi pubblicare il tuo codice assembly anche per questo?
Sir_Lagsalot,

1
Dopo aver esaminato il disassemblaggio e aver testato il codice, sembra che tu stia utilizzando un font bitmap fornito dal BIOS. Ciò può essere confermato dal fatto che il programma può generare lettere minuscole, simboli e punteggiatura non richiesti dalla sfida. Pertanto, il carattere è esterno al tuo programma e non memorizzato da esso (almeno secondo me).
Sir_Lagsalot,

@Skizz: puoi confermarlo? È ancora una soluzione estremamente piacevole, ma un po 'contro le specifiche.
ChristopheD,

1
@ChristopheD: Beh, JB ha commentato "Sento che avremo un lungo e doloroso dibattito su ciò che costituisce una biblioteca esterna." - si potrebbe sostenere che putsin Ruby c'è una biblioteca esterna. Sì, utilizza i caratteri di bios, a cui si accede tramite una derefence del puntatore (non c'è alcuna loadoperazione per ottenere i caratteri nella RAM). Forse piegare troppo le regole. Me ne sarei andato via se non fosse stato per quei fastidiosi bambini ;-)
Skizz

6

Script shell (codice + dati = 295 caratteri)

Spero che tail, gzip e dd non contino come "librerie esterne". Esegui come echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. Il font che ho usato è Small Fonts 7,5, anche se ho dovuto tagliare il discensore dalla Q.

Esempio di output

IL RAPIDO VOLUME MARRONE SALTA SUI CANI PIZZANTI.  VERAMENTE!

Codice (137 caratteri)

i=`od -tu1|cut -c9-`
echo P4
for a in {0..7}
do for b in $i
do tail -2 $0|zcat|dd bs=1 count=1 skip=$((8*b+a))
done
done>8
wc -c 8
cat 8

Sceneggiatura completa

(usare xxd -rper ricreare il file originale)

0000000: 693d 606f 6420 2d74 7531 7c63 7574 202d  i=`od -tu1|cut -
0000010: 6339 2d60 0a65 6368 6f20 5034 0a66 6f72  c9-`.echo P4.for
0000020: 2061 2069 6e20 7b30 2e2e 377d 0a64 6f20   a in {0..7}.do 
0000030: 666f 7220 6220 696e 2024 690a 646f 2074  for b in $i.do t
0000040: 6169 6c20 2d32 2024 307c 7a63 6174 7c64  ail -2 $0|zcat|d
0000050: 6420 6273 3d31 2063 6f75 6e74 3d31 2073  d bs=1 count=1 s
0000060: 6b69 703d 2428 2838 2a62 2b61 2929 0a64  kip=$((8*b+a)).d
0000070: 6f6e 650a 646f 6e65 3e38 0a77 6320 2d63  one.done>8.wc -c
0000080: 2038 0a63 6174 2038 0a1f 8b08 0000 0000   8.cat 8........
0000090: 0000 ffed cdb1 0a83 3014 8561 910e 8e8e  ........0..a....
00000a0: 193b dca1 631f 2084 9353 6ba3 a3e0 e2a8  .;..c. ..Sk.....
00000b0: 2fe0 d8e1 22d8 276f 9a50 e813 940e fdb8  /...".'o.P......
00000c0: 70f9 a753 247f 7829 f0b5 b9e2 c718 2322  p..S$.x)......#"
00000d0: 1ba9 e9a8 9688 6895 892a 7007 f0fe 701e  ......h..*p...p.
00000e0: b879 ef48 6e8c aa4f 219c d984 750d 0d91  .y.Hn..O!...u...
00000f0: e9b2 8c63 d779 3fcf c3d0 f76d eb7c e2d2  ...c.y?....m.|..
0000100: 1880 d4d7 4b6e 9296 b065 49ab 75c6 cc92  ....Kn...eI.u...
0000110: 1411 63f6 7de7 3489 9031 847c 3c9a 531d  ..c.}.4..1.|<.S.
0000120: e9a1 aa8f 803e 01                        .....>.

Spiegazione

  • odè il programma di utilità standard "dump ottale". L' -tu1opzione dice invece di produrre un dump decimale di singoli byte (una soluzione sufficiente per la mancanza di asc (), ord (), .charCodeAt (), ecc. Di bash)
  • P4è il numero magico per un file PBM in formato binario, che racchiude otto pixel in ciascun byte (rispetto P1al file PBM in formato ASCII). Vedrai come questo si rivela utile.
  • Per riga dell'output finale, il programma estrae un byte di otto pixel (corrispondente al codice ASCII e al numero di riga) dalla sezione dei dati compressi con gzip alla fine usando dd. ( tail -2 $0estrae le ultime due righe dello script; i dati compressi includono un byte di avanzamento riga 0x0a). Succede quindi che otto pixel sono la larghezza di un singolo carattere. I byte null che riempiono gli spazi tra i caratteri supportati sono facilmente comprimibili perché sono tutti uguali.
  • Tutto questo è scritto in un file chiamato "8". Poiché esistono esattamente otto righe (e anche otto pixel per byte), il numero di byte è la larghezza dell'output in pixel. L'altezza dell'uscita è anche inclusa in ciò che wc -cstampa il nome del file di input "8" dopo il conteggio dei byte.
  • Ora che l'intestazione è completa, i dati dell'immagine vengono stampati. Bash nota solo che le ultime due righe non sono comandi validi (l'ultima in realtà UTF-8 non valida) dopo che ha eseguito tutto ciò che stava prima.
  • Ho usato KZIP solo per comprimere la sezione dati, come ha fatto Ilmari Karonen per un'intera presentazione alla sfida dei 12 giorni di Natale. Come descritto qui, è essenzialmente necessario utilizzare un editor esadecimale per sostituire il formato dell'intestazione ZIP con un'intestazione gzip. Includere CRC-32 e le dimensioni del file dall'intestazione ZIP originale sembra non essere necessario.

2
Soluzione davvero bella (e breve)! Nella shell scripting l'uso di dd, tail e gzip non dovrebbe essere considerato come un imho esterno.
ChristopheD,

1
Ti dispiace aggiungere una spiegazione di come funziona? Sarebbe molto apprezzato
Mr. Llama,

2
Molto bello, grazie mille per la spiegazione. Tuttavia, l'utilizzo della versione "P4" non rispetta realmente quanto detto dall'OP "un formato bitmap in bianco e nero ASCII molto semplice ".
eregon,

5

Python 2, 248 247 byte

s=raw_input();k=len(s);print"P1",k*8,8
for i in range(k*24):a=s[i/3%k];j=max(".!".find(a)+1,ord(a)-62)*3;print int("00080084IMVAENBSIFERBSUF4UFQQEMVDT4NAP4MNDSI9MRTMRBARA4NBQRAMNBE4E94NURDARDNRDMLD95DSL7"[j:j+3],32)>>(i/3/k*3+i%3)&1," 0"*(i%3/2*5)

Utilizza un carattere 3x5, impacchettato in una stringa stampabile, 3 byte per carattere. Il carattere è chiaramente leggibile, sebbene n sia in minuscolo e la v potrebbe essere scambiata per au se non viene vista nel contesto.

Dimensione reale:
dimensione reale

Zoomato x3:
ingrandito x3

L'output è un PBM di tipo P1, come nell'esempio della sfida. È stata una sfida divertente.


4

Ruby 1.9, 346 byte (codice 122 + dati 224 byte)

Ecco il risultato:

CODEGOLF

(È carino, no?)

z=0..7;puts"P1\n#{(s=gets).size*8} 8",z.map{|i|s.bytes.flat_map{|o|z.map{|j|'DATA'.unpack('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

Il carattere è stato generato da figlet -f banner -w 1000 $LETTERS e questo script .

Corri con echo -n 'CODEGOLF.STACKEXCHANGE.COM!' | ruby script.rb > image.pbm.

Lo script genera tutte le righe e le stampa semplicemente.

Ecco un hexdump (usare xxd -r):

0000000: 7a3d 302e 2e37 3b70 7574 7322 5031 5c6e  z=0..7;puts"P1\n
0000010: 237b 2873 3d67 6574 7329 2e73 697a 652a  #{(s=gets).size*
0000020: 387d 2038 222c 7a2e 6d61 707b 7c69 7c73  8} 8",z.map{|i|s
0000030: 2e62 7974 6573 2e66 6c61 745f 6d61 707b  .bytes.flat_map{
0000040: 7c6f 7c7a 2e6d 6170 7b7c 6a7c 271c 1c1c  |o|z.map{|j|'...
0000050: 0800 1c1c 0000 0000 001c 1c1c 0008 1422  ..............."
0000060: 417f 4141 003f 4141 3f41 413f 003e 4101  A.AA.?AA?AA?.>A.
0000070: 0101 413e 003f 4141 4141 413f 007f 0101  ..A>.?AAAAA?....
0000080: 1f01 017f 007f 0101 1f01 0101 003e 4101  .............>A.
0000090: 7941 413e 0041 4141 7f41 4141 001c 0808  yAA>.AAA.AAA....
00000a0: 0808 081c 0040 4040 4041 413e 0042 2212  .....@@@@AA>.B".
00000b0: 0e12 2242 0001 0101 0101 017f 0041 6355  .."B.........AcU
00000c0: 4941 4141 0041 4345 4951 6141 007f 4141  IAAA.ACEIQaA..AA
00000d0: 4141 417f 003f 4141 3f01 0101 003e 4141  AAA..?AA?....>AA
00000e0: 4151 215e 003f 4141 3f11 2141 003e 4101  AQ!^.?AA?.!A.>A.
00000f0: 3e40 413e 007f 0808 0808 0808 0041 4141  >@A>.........AAA
0000100: 4141 413e 0041 4141 4122 1408 0041 4949  AAA>.AAAA"...AII
0000110: 4949 4936 0041 2214 0814 2241 0041 2214  III6.A"..."A.A".
0000120: 0808 0808 007f 2010 0804 027f 0027 2e75  ...... ......'.u
0000130: 6e70 6163 6b28 2751 3c2a 2729 5b6f 3e36  npack('Q<*')[o>6
0000140: 343f 6f2d 3633 3a6f 2f34 365d 5b69 2a38  4?o-63:o/46][i*8
0000150: 2b6a 5d7d 7d2a 2720 277d                 +j]}}*' '}

Ci vogliono 93 byte di codice quando si usa goruby:

ps"P1\n#{(s=gt).sz*8} 8",8.mp{|i|s.y.fl{|o|8.mp{|j|'DATA'.ua('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

L'uso di ZLib riduce la dimensione dei dati a 142 byte anziché a 224, ma aggiunge 43 byte nel codice, quindi 307 byte:

#coding:binary
require'zlib';z=0..7;puts"P1\n#{(s=gets).size*8} 8",z.map{|i|s.bytes.flat_map{|o|z.map{|j|Zlib.inflate("DATA").unpack('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

Il che dà un totale di 268 quando si utilizza goruby:

#coding:binary
rq'zlib';ps"P1\n#{(s=gt).sz*8} 8",8.mp{|i|s.y.fl{|o|8.mp{|j|Zlib.if("DATA").ua('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

2

Java 862 826:

Ecco un approccio diverso. Penso che "awt" non conti come lib esterna.

import java.awt.*;
class B extends Frame{String s="ABCDEFGHIJKLMNOPQRSTUVWXYZ .!";int l=29;static Robot r;int[][][]m=new int[l][8][8];
public void paint(Graphics g){for(int y=0;y<8;++y){int py=(y<3)?y:y+1;for(int a=0;a<l;++a)
for(int x=0;x<8;++x)
m[a][x][y]=(r.getPixelColor(8*a+x+17+x/4,py+81)).getRGB()<-1?1:0;}
System.out.println("P1\n"+(getTitle().length()*8)+" 8");
for(int y=0;y<8;++y){for(char c:getTitle().toCharArray()){int a=s.indexOf(c);
for(int x=0;x<8;++x)System.out.print(m[a][x][y]);}
System.out.println();}
System.exit(0);}
public B(String p){super(p);
setBackground(Color.WHITE);
setSize(400,60);
Label l=new Label(s);
l.setFont(new Font("Monospaced",Font.PLAIN,13));
add(l);
setLocation(9,49);    
setVisible(true);}    
public static void main(String a[])throws Exception{r=new Robot();    
new B(a[0]);}}

E non golfato:

import java.awt.*;

class PBM extends Frame
{
    String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ .!";
    int l=29;
    Robot robot;
    int[][][] map = new int[l][8][8];

    static boolean init = false;

    public void paint (Graphics g)
    {    
        for (int y = 0; y < 8; ++y)    
        {    
            int py = (y < 3) ? y : y +1;    
            for (int a = 0; a < l; ++a)
            {    
                for (int x = 0; x < 8; ++x)    
                {    
                    map[a][x][y] = (robot.getPixelColor (8*a+x+17+x/4, py+81)).getRGB () < -1 ? 1 : 0;    
                }    
            }    
        }

        System.out.println("P1\n"+(getTitle().length()*8)+" 8");

        for (int y = 0; y < 8; ++y) {    
            for (char c : getTitle ().toCharArray ()) {    
                int a = s.indexOf (c);    
                for (int x = 0; x < 8; ++x) {    
                    System.out.print (map[a][x][y]);    
                }
            }
            System.out.println ();
        }
        System.exit (0);
    }   

    public PBM (String p) throws Exception    
    {    
        super (p);    
        robot = new Robot ();    
        setBackground (Color.WHITE);    
        setSize (400, 60);    
        Label l=new Label(s);    
        l.setFont (new Font ("Monospaced", Font.PLAIN, 13));
        add(l);
        setLocation (9,49);
        setVisible (true);
    }

    public static void main (String args[]) throws Exception
    {
        new PBM (args[0]);
    }    
}

Il robot è il modo in qualche modo curioso di Java di chiamare getPixel. Creo un'etichetta con l'alfabeto e misuro dove si trova un pixel per ogni lettera.

Nel metodo di pittura, int py = (y < 3) ? y : y +1;e(8*a+x+17+x/4, py+81) è il modo complicato, per regolare la posizione nel carattere. Huuuh! altrimenti avrebbe bisogno di 9 righe e ogni quarta lettera c'è un pixel aggiuntivo in orizzontale. Prove ed errori mi hanno portato a questa soluzione.

Quindi viene scritta l'intestazione del PBM e ciascuna riga del messaggio. Il messaggio viene passato come titolo del frame.

Questo è tutto. Non è il codice più breve, ma non è stata necessaria la pittura manuale dei caratteri.

Forse potrebbe essere più breve in BeanShell o Scala.

E ora - come si presenta?

java B "JAVA.CAFE BABE" > jcb.pbm

Zoom multipli applicati: java.cafe bambino PNG

senza zoom: java.cafe JPG

Non che il numero di caratteri sia il numero di caratteri della soluzione Perl mischiato.

(ha giocato un po 'di più. Ha reso Robot statico, il che evita una dichiarazione di eccezione.)


Approccio originale, ben fatto!
ChristopheD,

1
+1 per originalità, ma eww ... se vuoi ridimensionare una bitmap, usa l'interpolazione del vicino più vicino.
Ilmari Karonen,

Ho usato eog(Eye of Gnome) e uno screenshot. Carico una versione non scalata jpg; forse il tuo browser utilizza l'interpolazione del vicino più vicino :).
utente sconosciuto dal

1

C ++ TROPPO GRANDE PER VINCERE

Ho scritto un programma di disegno PPM completo in C ++, con il mio font bitmap. Anche eliminare tutte le funzioni non necessarie è ancora enorme rispetto alle risposte qui a causa della definizione per il carattere.

Ad ogni modo, ecco l'output di HELLO WORLD: inserisci qui la descrizione dell'immagine

E il codice:

ppmdraw.h

#ifndef PPMDRAW_H
#define PPMDRAW_H

#include <fstream>
#include <sstream>
#include <map>
#include <bitset>
#include <vector>

struct pixel{
    unsigned char r;
    unsigned char g;
    unsigned char b;

    bool equals(pixel p){
        return (r == p.r && g == p.g && b == p.b);
    }
};

class PPMDraw
{
    public:
        PPMDraw(int w, int h);

        virtual ~PPMDraw();

        void fill(unsigned char r, unsigned char g, unsigned char b);

        void set_color(unsigned char r, unsigned char g, unsigned char b);

        void draw_point(int x, int y);

        void draw_char(int x, int y, char c);
        void draw_string(int x, int y, std::string text);

        bool save(std::string file);

    private:

        int width;
        int height;

        pixel * image;

        std::vector<bool> checked;

        unsigned char red;
        unsigned char green;
        unsigned char blue;

        void init_alpha();
        std::map<char, std::bitset<48> > font;

};

#endif // PPMDRAW_H

ppmdraw.cpp

#include "PPMDraw.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cmath>
#include <map>
#include <bitset>
#include <vector>

// standard constructor
PPMDraw::PPMDraw(int w, int h){
    width = w;
    height = h;

    // make an array to hold all the pixels, r, g, b for each
    image = new pixel[width * height];

    // a bitset to use for functions that have to check which pixels have been worked on
    checked = std::vector<bool>();
    for(int i = 0; i < width * height; i++){
        checked.push_back(false);
    }

    init_alpha();
}


PPMDraw::~PPMDraw(){
    if(image != nullptr){
        delete[] image;
    }
}



void PPMDraw::fill(unsigned char r, unsigned char g, unsigned char b){
    for(int i = 0; i < width * height; i++){
        image[i + 0] = pixel{r, g, b};
    }
}

void PPMDraw::set_color(unsigned char r, unsigned char g, unsigned char b){
    red = r;
    green = g;
    blue = b;
}

void PPMDraw::draw_point(int x, int y){
    if(x >= 0 && x < width && y >= 0 && y < height){
        image[y * width + x] = pixel{red, green, blue};
    }
}

void PPMDraw::draw_char(int x, int y, char c){
    std::bitset<48> letter = font[c];
    int n = 47;
    for(int i = 0; i < 6; i++){
        for(int j = 0; j < 8; j++){
            if(letter[n]){
                draw_point(x + i, y + j);
            }
            n--;
        }
    }
}
void PPMDraw::draw_string(int x, int y, std::string text){
        for(unsigned int i = 0; i < text.length(); i++){
            draw_char(x + 6 * i, y, text[i]);
        }

}



bool PPMDraw::save(std::string file){
    std::ofstream save(file.c_str(), std::ios_base::out | std::ios_base::binary);
    if(save.is_open()){
        save << "P6" << std::endl;
        save << width << " " << height << std::endl;
        save << "255" << std::endl;
        unsigned char * temp = new unsigned char[height * width * 3];
        for(int i  = 0; i < height * width; i++){
            temp[i * 3 + 0] = image[i].r;
            temp[i * 3 + 1] = image[i].g;
            temp[i * 3 + 2] = image[i].b;
        }
        save.write(reinterpret_cast<const char *> (temp), height*width*3*sizeof(unsigned char));
        delete temp;
        save.close();
        return true;
    }else{
        return false;
    }


}

void PPMDraw::init_alpha(){
    // Define a simple font for drawing text
    font[' '] = std::bitset<48>  (std::string("000000000000000000000000000000000000000000000000"));
    font['!'] = std::bitset<48>  (std::string("000000000000000011110110000000000000000000000000"));
    font['"'] = std::bitset<48>  (std::string("000000001100000000000000110000000000000000000000"));
    font['#'] = std::bitset<48>  (std::string("001010001111111000101000111111100010100000000000"));
    font['$'] = std::bitset<48>  (std::string("001001000101010011111110010101000100100000000000"));
    font['%'] = std::bitset<48>  (std::string("000000100100110000010000011000001000010000000000"));
    font['&'] = std::bitset<48>  (std::string("000111001110001010110010110011000000001000000000"));
    font['\\'] = std::bitset<48>  (std::string("100000000110000000010000000011000000001000000000"));
    font['('] = std::bitset<48>  (std::string("000000000000000001111100100000100000000000000000"));
    font[')'] = std::bitset<48>  (std::string("000000001000001001111100000000000000000000000000"));
    font['*'] = std::bitset<48>  (std::string("010010000011000011100000001100000100100000000000"));
    font['+'] = std::bitset<48>  (std::string("000100000001000001111100000100000001000000000000"));
    font[','] = std::bitset<48>  (std::string("000000000000000000000110000000000000000000000000"));
    font['-'] = std::bitset<48>  (std::string("000100000001000000010000000100000001000000000000"));
    font['.'] = std::bitset<48>  (std::string("000000000000000000000100000000000000000000000000"));
    font['/'] = std::bitset<48>  (std::string("000000100000110000010000011000001000000000000000"));
    font['0'] = std::bitset<48>  (std::string("011111001000001010000010100000100111110000000000"));
    font['1'] = std::bitset<48>  (std::string("000000001000001011111110000000100000000000000000"));
    font['2'] = std::bitset<48>  (std::string("010011101001001010010010100100100111001000000000"));
    font['3'] = std::bitset<48>  (std::string("010001001000001010000010100100100110110000000000"));
    font['4'] = std::bitset<48>  (std::string("111100000001000000010000000100001111111000000000"));
    font['5'] = std::bitset<48>  (std::string("111001001001001010010010100100101001110000000000"));
    font['6'] = std::bitset<48>  (std::string("011111001001001010010010100100101000110000000000"));
    font['7'] = std::bitset<48>  (std::string("100000001000000010000110100110001110000000000000"));
    font['8'] = std::bitset<48>  (std::string("011011001001001010010010100100100110110000000000"));
    font['9'] = std::bitset<48>  (std::string("011000001001000010010000100100000111111000000000"));
    font[':'] = std::bitset<48>  (std::string("000000000000000001000100000000000000000000000000"));
    font[';'] = std::bitset<48>  (std::string("000000000000000001000110000000000000000000000000"));
    font['<'] = std::bitset<48>  (std::string("000000000001000000101000010001000000000000000000"));
    font['='] = std::bitset<48>  (std::string("001010000010100000101000001010000000000000000000"));
    font['>'] = std::bitset<48>  (std::string("000000000100010000101000000100000000000000000000"));
    font['?'] = std::bitset<48>  (std::string("010000001000000010001010100100000110000000000000"));
    font['@'] = std::bitset<48>  (std::string("011111001000001010111010101010100111001000000000"));
    font['A'] = std::bitset<48>  (std::string("011111101001000010010000100100000111111000000000"));
    font['B'] = std::bitset<48>  (std::string("111111101001001010010010100100100110110000000000"));
    font['C'] = std::bitset<48>  (std::string("011111001000001010000010100000100100010000000000"));
    font['D'] = std::bitset<48>  (std::string("111111101000001010000010100000100111110000000000"));
    font['E'] = std::bitset<48>  (std::string("111111101001001010010010100100101000001000000000"));
    font['F'] = std::bitset<48>  (std::string("111111101001000010010000100100001000000000000000"));
    font['G'] = std::bitset<48>  (std::string("011111001000001010000010100010100100110000000000"));
    font['H'] = std::bitset<48>  (std::string("111111100001000000010000000100001111111000000000"));
    font['I'] = std::bitset<48>  (std::string("100000101000001011111110100000101000001000000000"));
    font['J'] = std::bitset<48>  (std::string("000011000000001000000010000000101111110000000000"));
    font['K'] = std::bitset<48>  (std::string("111111100001000000010000001010001100011000000000"));
    font['L'] = std::bitset<48>  (std::string("111111100000001000000010000000100000001000000000"));
    font['M'] = std::bitset<48>  (std::string("111111101000000001100000100000001111111000000000"));
    font['N'] = std::bitset<48>  (std::string("111111100100000000100000000100001111111000000000"));
    font['O'] = std::bitset<48>  (std::string("011111001000001010000010100000100111110000000000"));
    font['P'] = std::bitset<48>  (std::string("111111101001000010010000100100001111000000000000"));
    font['Q'] = std::bitset<48>  (std::string("011111001000001010001010100001000111101000000000"));
    font['R'] = std::bitset<48>  (std::string("111111101001000010010000100110001111011000000000"));
    font['S'] = std::bitset<48>  (std::string("011000101001001010010010100100101000110000000000"));
    font['T'] = std::bitset<48>  (std::string("100000001000000011111110100000001000000000000000"));
    font['U'] = std::bitset<48>  (std::string("111111000000001000000010000000101111110000000000"));
    font['V'] = std::bitset<48>  (std::string("111110000000010000000010000001001111100000000000"));
    font['W'] = std::bitset<48>  (std::string("111111100000001000001100000000101111111000000000"));
    font['X'] = std::bitset<48>  (std::string("110001100010100000010000001010001100011000000000"));
    font['Y'] = std::bitset<48>  (std::string("110000000010000000011110001000001100000000000000"));
    font['Z'] = std::bitset<48>  (std::string("100001101000101010010010101000101100001000000000"));
    font['['] = std::bitset<48>  (std::string("000000001111111010000010100000100000000000000000"));
    font['\''] = std::bitset<48>  (std::string("100000000110000000010000000011000000001000000000"));
    font[']'] = std::bitset<48>  (std::string("000000001000001010000010111111100000000000000000"));
    font['^'] = std::bitset<48>  (std::string("001000000100000010000000010000000010000000000000"));
    font['_'] = std::bitset<48>  (std::string("000000100000001000000010000000100000001000000000"));
    font['`'] = std::bitset<48>  (std::string("000000001000000001000000000000000000000000000000"));
    font['a'] = std::bitset<48>  (std::string("000001000010101000101010001010100001111000000000"));
    font['b'] = std::bitset<48>  (std::string("111111100001001000010010000100100000110000000000"));
    font['c'] = std::bitset<48>  (std::string("000111000010001000100010001000100001010000000000"));
    font['d'] = std::bitset<48>  (std::string("000011000001001000010010000100101111111000000000"));
    font['e'] = std::bitset<48>  (std::string("000111000010101000101010001010100001101000000000"));
    font['f'] = std::bitset<48>  (std::string("000100000111111010010000100100000000000000000000"));
    font['g'] = std::bitset<48>  (std::string("001100100100100101001001010010010011111000000000"));
    font['h'] = std::bitset<48>  (std::string("111111100001000000010000000100000000111000000000"));
    font['i'] = std::bitset<48>  (std::string("000000000000000001011110000000000000000000000000"));
    font['j'] = std::bitset<48>  (std::string("000000100000000100000001010111100000000000000000"));
    font['k'] = std::bitset<48>  (std::string("111111100000100000010100001000100000000000000000"));
    font['l'] = std::bitset<48>  (std::string("000000000000000011111110000000000000000000000000"));
    font['m'] = std::bitset<48>  (std::string("000111100001000000001000000100000001111000000000"));
    font['n'] = std::bitset<48>  (std::string("001111100001000000010000000100000001111000000000"));
    font['o'] = std::bitset<48>  (std::string("000111000010001000100010001000100001110000000000"));
    font['p'] = std::bitset<48>  (std::string("001111110010010000100100001001000001100000000000"));
    font['q'] = std::bitset<48>  (std::string("000110000010010000100100001001000011111100000000"));
    font['r'] = std::bitset<48>  (std::string("000000000011111000010000000100000000000000000000"));
    font['s'] = std::bitset<48>  (std::string("000000000001001000101010001010100010010000000000"));
    font['t'] = std::bitset<48>  (std::string("000000000010000011111110001000000000000000000000"));
    font['u'] = std::bitset<48>  (std::string("000111000000001000000010000000100001110000000000"));
    font['v'] = std::bitset<48>  (std::string("000110000000010000000010000001000001100000000000"));
    font['w'] = std::bitset<48>  (std::string("000111100000001000000100000000100001111000000000"));
    font['x'] = std::bitset<48>  (std::string("001000100001010000001000000101000010001000000000"));
    font['y'] = std::bitset<48>  (std::string("001100000000100000000111000010000011000000000000"));
    font['z'] = std::bitset<48>  (std::string("010001100100101001010010011000100000000000000000"));
    font['{'] = std::bitset<48>  (std::string("000000000000000001101100100100100000000000000000"));
    font['|'] = std::bitset<48>  (std::string("000000000000000011111110000000000000000000000000"));
    font['}'] = std::bitset<48>  (std::string("000000000000000010010010011011000000000000000000"));
    font['~'] = std::bitset<48>  (std::string("000100000010000000010000000010000001000000000000"));
}

main.cpp

#include "PPMDraw.h"
#include <iostream>

int main(){
    // ask for input
    std::string input;
    std::cout << "ENTER YOUR TEXT" << std::endl;
    getline(std::cin, input);
   // get size for image
  int width = input.size() * 6;
   PPMDraw image = PPMDraw(width, 8);
   image.fill(255, 255, 255);
   image.set_color(0, 0, 0);
   image.draw_string(0, 0, input);
   image.save("text.ppm");
}

Makefile

CC = g++
CFLAGS = -Wall -c -std=c++11
LFLAGS = -Wall
OBJS = main.o PPMDraw.o

list: $(OBJS)
    $(CC) $(LFLAGS) $(OBJS) -o text2ppm

main.o: PPMDraw.h
    $(CC) $(CFLAGS) main.cpp

PPMDraw.o: PPMDraw.h
    $(CC) $(CFLAGS) PPMDraw.cpp

clean:
    rm *.o main

Se sei interessato, la libreria PPMDraw completa è qui :


1
Ho trovato i tuoi caratteri molto utili!
Ludwik,

1

SmileBASIC, 231 byte

LINPUT C$?"P1
?8,LEN(C$)*8WHILE""<C$A=ASC(SHIFT(C$))D=ASC("*N.JZ`;O:²ÞøäüÄho"[A-65+12*(A<34)+47*(A<47)])FOR I=0TO 4B$=BIN$(VAL("7535712074617252"[D>>5<<1OR 1AND D>>I]),8)WHILE""<B$?POP(B$),
WEND?NEXT?"0 "*24WEND

inserisci qui la descrizione dell'immagine

Ogni personaggio contiene solo 2 diversi pattern di righe, scelti da una "palette" di 8 combinazioni. I dati per ciascun simbolo sono memorizzati in 1 byte, con la tavolozza memorizzata separatamente.

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.