language agnostic - Código Golf: Siete segmentos
language-agnostic code-golf (26)
El reto
El código más corto por recuento de caracteres para generar una representación de visualización de siete segmentos de un número hexadecimal dado.
Entrada
La entrada está compuesta de dígitos [0-9] y caracteres hexadecimales tanto en mayúsculas como minúsculas [a-fA-F] solamente. No hay necesidad de manejar casos especiales.
Salida
La salida será la representación de siete segmentos de la entrada, usando esas caras ASCII :
_ _ _ _ _ _ _ _ _ _ _ _
| | | _| _| |_| |_ |_ | |_| |_| |_| |_ | _| |_ |_
|_| | |_ _| | _| |_| | |_| _| | | |_| |_ |_| |_ |
Restricciones
El uso de lo siguiente está prohibido: eval, exec, system, figlet, toilet y bibliotecas externas.
Casos de prueba:
Input:
deadbeef
Output:
_ _ _ _ _
_||_ |_| _||_ |_ |_ |_
|_||_ | ||_||_||_ |_ |
Input:
4F790D59
Output:
_ _ _ _ _ _
|_||_ ||_|| | _||_ |_|
|| | _||_||_| _| _|
El recuento de códigos incluye entrada / salida (es decir, programa completo).
C ++, 286 bytes
Jeje, todo el mundo ha ideado una forma más concisa para representar los datos.
De todos modos, para que no sea una pérdida de tiempo completa (entrada desde la línea de comandos):
#include<cstdio>
#define P(x)putchar(x);
int main(int,char**v){int i,j,d[]={0,6947821,0,7209841,7734140,1180575,8257861,
3933037,1442811};char*p,c[]="|_|";for(++v;*v;++v){for(i=0;i<9;i+=3){for(p=*v;*p;
++p){for(j=0;j<3;++j)P(1<<((*p>96?*p-32:*p)-48)&d[i+j]?c[j]:32)P(32)}P(10)}P(10)
}}
Y no confundido:
#include <cstdio>
void out(const char* s)
{
int i, j;
const char* c = "|_|";
unsigned d[9] = {0, 6947821, 0, 7209841, 7734140, 1180575, 8257861, 3933037, 1442811};
for (i = 0; i < 9; i += 3) {
for (const char* p = s; *p; ++p) {
for (j = 0; j != 3; ++j)
putchar(1 << ((*p > 96 ? *p - 32 : *p) - ''0'') & d[j + i] ? c[j] : '' '');
putchar('' '');
}
putchar(''/n'');
}
}
int main(int, char** argv)
{
for (++argv;*argv;) {
out(*argv++);
putchar(''/n'');
}
}
Los números mágicos se refieren a qué caracteres tienen un _ o un | en una posición particular. Por ejemplo, si 0, 3, 5 y ''A'' tienen todos | en algún lugar, el número sería 1 << n(''0'') | 1 << n(''3'') | 1 << n(''5'') | 1 << n(''A'')
1 << n(''0'') | 1 << n(''3'') | 1 << n(''5'') | 1 << n(''A'')
1 << n(''0'') | 1 << n(''3'') | 1 << n(''5'') | 1 << n(''A'')
- donde n(x)
significa x - ''0''
. Esto supone al menos enteros de 32 bits, ya que hay un pequeño espacio entre ''9''
y ''A''
en el gráfico ASCII.
Ambos códigos fueron editados recientemente: use matriz unidimensional en lugar de bidimensional (d), propio " toupper
" no a prueba de errores en lugar de incluir cctype, movido todo a main, otra forma de bucle sobre argumentos de línea de comando, más condensado declaraciones variables, valores mágicos en lugar de constantes char y algunos otros cambios menores.
F #, 294 caracteres
No hice nada inteligente, pero aun así obtuve una puntuación respetable.
let rec G s=for r in[" _ _ _ _ _ _ _ _ _ _ _ _ ";"| | | _| _||_||_ |_ ||_||_||_||_ | _||_ |_ ";"|_| ||_ _| | _||_| ||_| _|| ||_||_ |_||_ | "]do Seq.iter(printf"%s"<<S r)s;printfn""
and S a h=a.Substring(3*(int h-if h<''A''then 48 elif h<''a''then 55 else 87),3)
Con espacios en blanco para mayor claridad:
let rec G s=
for r in[" _ _ _ _ _ _ _ _ _ _ _ _ ";
"| | | _| _||_||_ |_ ||_||_||_||_ | _||_ |_ ";
"|_| ||_ _| | _||_| ||_| _|| ||_||_ |_||_ | "] do
Seq.iter (printf "%s" << S r) s;
printfn""
and S a h=
a.Substring(3*(int h - if h<''A''
then 48
elif h<''a''
then 55
else 87),3)
Muestra:
G("abcdefFEDCBA9876543210")
Salida:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_||_ | _||_ |_ |_ |_ _|| |_ |_||_||_| ||_ |_ |_| _| _| || |
| ||_||_ |_||_ | | |_ |_||_ |_|| | _||_| ||_| _| | _||_ ||_|
Ruby: 175
d="3yy0nxcoypnk4185nbr3k9ddjlhe".to_i 36
s=gets.chomp
o=''''
for i in 0..2
s.each_char{|c|q=d>>c.to_i(16)*3
"|_|".each_char{|z|o<<(q&1>0?z:'' '')
q>>=1}}
d>>=48
o<<"/n"
end
puts o
Y cuando es un poco más legible ...
d="3yy0nxcoypnk4185nbr3k9ddjlhe".to_i 36
s=gets.chomp
o=''''
for i in 0..2
s.each_char { |c|
q = d >> c.to_i(16) * 3
"|_|".each_char { |z|
o << (q & 1 > 0 ? z : '' '')
q >>= 1
}
}
d >>= 48
o << "/n"
end
puts o
BrainF ***, 920 906 885 868 863 860 858 caracteres para reloj digital
Empecé con esto en el código de reloj digital (ahora cerrado) golf, por lo que también es compatible. Todo: manejar en minúsculas.
-[>+<-----]->----[>,]<[<]>>[[->]<+[-<+]->]<+>-[>]+++[[<]>>[[>]>[>]+[<]<[<]+[>]>[
>]+[-<+]->[[>]>[>]<+[<]<[<]>+[>]+[-<+]->-]->]<[<]>+[-[>]+[-<+]+<[<]>[[>]+[-<+]->
+<[<]>-]>+]+[-->]+[->]-[>-<-----]>+++>-->->----<<<[>>+++>+++++>-[+++<]>]-<+[>]-[
<]>>>+[-<<+[->+]<<-[-[++>->>[>]>>+++++>>+++++>>>>>+++++>>>+++++++>>>>>>+++++>>>+
++++>>+[<+]<[<]<]>[-<++>>>[>]<--->+>+>->++++++>+>-->>>>>>>+++>-->-->>+>+>-->->->
>+++++>+[<++++]<[<]]<]>[-<+>>>[>]<--->++++++>+>-->+>-->+++++>>>>>>>+++>->-->>-->
->>->+>>-->+[<++++]<[<]]<+>-[[>]>[>]<[-]<[<]<[<]>-]>[>]>[>]+<-[-[-[-[-[-[-[-[-[[
<]<<.>...>>[>]<-]>[<+[<]<<.>.<.>.>>[>]<->]<]>[<+[<]<..>>[>]<->]<]>[<+[<]<<<<.>>>
.>>[>]<->]<]>[<+[<]<....>>[>]<->]<]>[<+[<]<<.<.>>..>>[>]<->]<]>[<+[<]<..<.>.>>[>
]<->]<]>[<+[<]<.<<.>.>.>>[>]<->]<]>[<+[<]<<.<.>.>.>>[>]<->]<]>[<+[<]<.<<.>>..>>[
>]<->]<<[[-]<]-[<]>>>+]++++++++++.[>]<[[-]<]+[-<+]-[>]<-]
$ echo 01:23456789DEADBEEF | beef clock.b
_ _ _ _ _ _ _ _ _ _ _ _ _
| | | . _| _| |_| |_ |_ | |_| |_| _| |_ |_| _| |_ |_ |_ |_
|_| | . |_ _| | _| |_| | |_| _| |_| |_ | | |_| |_| |_ |_ |
Esto depende en gran medida de que la plataforma sea de 8 bits.
C89 (181 caracteres; args)
char*q,a=3;p(l){putchar(*q?"|#]u&rzc~vn:X=ZJ"[*q-(*q&64?55:48
)&15]+1>>l&1?"|_||_|_"[l]:32:10);}main(r,v)char**v;{for(;a--
;p())for(q=v[1];*q;++q)for(r=3;r--;)p(a-2?5-r-a*3:r-1?7:6);}
C89 (192 caracteres; stdin
)
char*q,b[9],gets(char*),a=3;p(l){putchar(*q?"|#]u&rzc~vn:X=ZJ"[*
q-(*q&64?55:48)&15]+1>>l&1?"|_||_|_"[l]:32:10);}main(r){for(gets
(b);a--;p())for(q=b;*q;++q)for(r=3;r--;)p(a-2?5-r-a*3:r-1?7:6);}
Explicación:
char*q,b[9],gets(char*),a=3;
p(l){
putchar(*q?
/*
* Each element of the magic string is decremented so 0x7F is
* ''~'' (0x7E). Each bit before the decrement represents
* a segment (thus "8" is 0x7F (0x7E), i.e. all 7 bits on).
* Bit 7 is always cleared so p(7) always prints a space.
*/
"|#]u&rzc~vn:X=ZJ"
[*q-(*q&64?55:48)&15]+1 /* d[ascii2hex(*q)] + 1 */
>>l&1 /* Is bit ''l'' set? */
?"|_||_|_"[l] /* Yes; choose _ or | by position. */
:32 /* No; enter a space. */
:10); /* End of line. */
}
main(r){
for(gets(b);a--;p()) /* Grab input and loop through each of 3 lines (a = 2, 1, 0). */
for(q=b;*q;++q) /* Iterate across input. */
for(r=3;r--;) /* For each of three characters across... */
p(a-2?5-r-a*3:r-1?7:6); /* Print the segment, mapping position to the bit. */
}
Golfscript - 116 caracteres
$ echo -n deadbeef | ./golfscript.rb led.gs
_ _ _ _ _
_||_ |_| _||_ |_ |_ |_
|_||_ | ||_||_||_ |_ |
Asegúrese de guardar sin una nueva línea adicional en el extremo o la cadena de entrada se imprimirá al final.
{32:^|}%:
{^'' _'':$@''14bd''{?~!=}:&~^}%n
{:x'' |'':|/'1237d''&$x''017c''&|x''56bcef''&}%n
{:x|/'134579''&$x''147af''&|x''2cef''&}%
Cómo funciona
Observe que hay más segmentos activados que desactivados para el rango 0-F. Enumere las excepciones (dígitos que tienen el segmento desactivado) para cada segmento.
#Python version of the algorithm above
s=raw_input().lower()
J=''''.join()
print J('' ''+''_ ''[c in''14bd'']+'' ''for c in s)
print J(''| ''[c in''1237d'']+''_ ''[c in''017c'']+''| ''[c in''56bcef'']for c in s)
print J(''| ''[c in''134579'']+''_ ''[c in''147af'']+''| ''[c in''2cef'']for c in s)
Java 1.5 - 272 caracteres con espacios en blanco innecesarios eliminados
Mucho más corta que la versión anterior, usando algunas ideas de JRL. Podría acortarse mediante el uso de argumentos de línea de comandos, pero eso va en contra de la especificación.
class D{public static void main(String[]a){char[]q=new java.util.Scanner
(System.in).nextLine().toCharArray();int j=0,k;for(;j<9;j+=3){for(int c:
q){for(k=j;k<j+3;k++){System.out.print(("{H=mNgwI/177o_v3|7/027".charAt(
"0123456789abcdef".indexOf(c|32))&"/0/1/0/2/4/10/20 @".charAt(k))>0?
" _ |_||_|".charAt(k):32);}}System.out.println();}}}
Perl, 134 caracteres
Todos los saltos de línea pueden ser eliminados.
@s=unpack"C*",~"P/xdbLI/xc3a`[/@AB/xe0t/xc8df";
$_=<>;for$s(6,3,0){print map$s[hex$&]&1<<$_+$s?$_%2?"_":"|":" ",
0..2while/./g;print$/}
Explicación
@s
almacena los bits para cada segmento. Las entradas están en orden de 0 a F (gracias a hex()
) y los bits se asignan a los segmentos en este orden:
6 7 x
3 4 5
0 1 2
siendo 0
el LSB. (El bit 6 no está en uso). Los valores se almacenan empaquetados en la cadena de bits invertidos por lo que hay muchos más caracteres imprimibles; el operador ~
voltea los bits y descomprimir me da números (los operadores bit a bit de Perl son mucho más torpes cuando se trata de cadenas de caracteres).
Con los datos en la mano, leo la entrada y procedo a recorrerla tres veces; la única diferencia entre los tres bucles es la máscara de bits requerida. Para cada carácter de entrada se imprimen tres caracteres de salida. El personaje que se imprimirá es
$s[ hex $& ] & (1 << ($_ + $s) )
? ($_ % 2 ? "_" : "|" )
: " "
donde @s
es la tabla de búsqueda, $s
es el cambio en efecto dependiendo de la fila, y $_
es si estamos imprimiendo el primer, segundo o tercer carácter en la fila. Si el bit correcto en la entrada de la tabla de búsqueda es falso, imprime un espacio; de lo contrario, imprime un "|" en los lados o un "_" en el medio.
x86 (146 bytes; args)
Inspirado por Jonas Gulle en Code Golf: The wave . Usualmente escribiría un ELF de Linux de 32 bits, pero un DOS COM de 16 bits es mucho más pequeño (instrucciones más cortas, cero sobrecarga).
46 instrucciones y 24 palabras no ejecutadas. (Se destacan bastante obviamente al final, ¿no?) Nada complicado como reutilizar el código como datos; probablemente no ahorraría más de 10 bytes de todos modos.
C:/>od -xAn ss.com c930 82be ac00 0d3c 3e74 403c 027e 0904 0f24 0198 bbc8 0162 c301 0eb4 078a 0424 0474 7cb0 02eb 20b0 10cd 078a 0224 0474 5fb0 02eb 20b0 10cd 078a 0124 0474 7cb0 02eb 20b0 10cd bdeb f980 7420 b014 cd0d b010 cd0a 6610 c381 0010 0000 c180 eb10 c3a1 0002 0202 0200 0202 0202 0002 0002 0202 0105 0303 0607 0106 0707 0607 0304 0606 0107 0306 0301 0107 0307 0705 0706 0406 C:/>ss deadbeef _ _ _ _ _ _||_ |_| _||_ |_ |_ |_ |_||_ | ||_||_||_ |_ |
Esto simplemente va letra por letra imprimiendo la primera línea, luego la segunda línea, etc. utilizando 3 bytes para almacenar los 9 bits de datos para cada personaje. Obviamente, queda espacio para la mejora ... (Esta es la primera vez que NASM sintaxis de NASM , estoy más acostumbrado al gas pero no pude convencerlo de que genere un binario en bruto).
org 0x100
; initialize registers
xor cl,cl
; reset ds:[si] to start of arguments
start:
mov si,0x82
; load one character of arguments
read:
lodsb
cmp al,0xd
je next
; transform [0-9A-Fa-f] to [/x00-/x0f]
cmp al,0x40
jle skipa
add al,0x9
skipa:
and al,0xf
; load font definition
cbw
add ax,cx
mov bx,letters
add bx,ax
mov ah,0xe
; print first char
mov al,[bx]
and al,0x4
jz s1
mov al,0x7c
jmp short w1
s1:
mov al,0x20
w1:
int 0x10
; print second char
mov al,[bx]
and al,0x2
jz s2
mov al,0x5f
jmp short w2
s2:
mov al,0x20
w2:
int 0x10
; print third char
mov al,[bx]
and al,0x1
jz s3
mov al,0x7c
jmp short w3
s3:
mov al,0x20
w3:
int 0x10
; next character
jmp short read
; print newline
next:
cmp cl,0x20
je end
mov al,0xd
int 0x10
mov al,0xa
int 0x10
add ebx,0x10
add cl,0x10
jmp short start
end:
ret
letters:
db 2,0,2,2,0,2,2,2,2,2,2,0,2,0,2,2
db 5,1,3,3,7,6,6,1,7,7,7,6,4,3,6,6
db 7,1,6,3,1,3,7,1,7,3,5,7,6,7,6,4
C # - 576 caracteres (sin linebreaks)
Probablemente haya una mejor manera de hacerlo, pero esta es mi solución:
using C=System.Console;class Z{static void Main(){new Z();}int L=0;Z(){
try{var s=C.ReadLine().ToUpper();C.Clear();foreach(var c in s){int n=(
int)c;var p=(n==48?"_ ;| |;|_|":n==49?"; |; |":n==50?"_; _|;|_":n==51
?"_; _|; _|":n==52?";|_|; |":n==53?"_;|_; _|":n==54?"_;|_;|_|":n==55?
"_; |; |":n==56?"_;|_|;|_|":n==57?"_;|_|; _|":n==65?"_;|_|;| |":n==66
?";|_;|_|":n==67?"_;|;|_":n==68?"; _|;|_|":n==69?"_;|_;|_":n==70?"_;|_;|"
:";;").Split('';'');P(0);C.Write(" "+p[0]);P(1);C.Write(p[1]);P(2);C.Write
(p[2]);L+=4;}C.WriteLine();}catch{}}void P(int t){C.SetCursorPosition(L,t);}}
PHP, 232 characateres
$d=str_split('' _ | ||_ |_| _| || 124066153155046135134166144145142034173054133137'',3);
foreach(str_split(strtolower($s))as$c){
$c=hexdec($c)+8;$r[0].=$d[$d[$c][0]];$r[1].=$d[$d[$c][1]];$r[2].=$d[$d[$c][2]];i
}
echo implode("/n",$r);
Explicación
# Array containing possible lines
$d=array(
0 => '' '',
1 => '' _ '',
2 => ''| |'',
3 => ''|_ '',
4 => ''|_|'',
5 => '' _|'',
6 => '' |'',
7 => ''| ''
);
# Array mapping characters to 3 lines
$m=array(
0 => ''124'', # i.e. The character ''0'' is represented by $d[1], $d[2] and $d[4]
1 => ''066'',
2 => ''153'',
3 => ''155'',
4 => ''046'',
5 => ''135'',
6 => ''134'',
7 => ''166'',
8 => ''144'',
9 => ''145'',
a => ''142'',
b => ''034'',
c => ''173'',
d => ''054'',
e => ''133'',
f => ''137'',
);
# traverse $s and append to array $r
foreach (str_split(strtolower($s)) as $c) {
$r[0].=$d[$m[$c][0]];
$r[1].=$d[$m[$c][1]];
$r[2].=$d[$m[$c][2]];
}
# echo $r
echo implode("/n",$r);
Optimizaciones:
- Las matrices se generan dinámicamente usando
str_split()
- Ambas matrices se unen en una
- Los personajes se asignan numéricamente usando
hexdec()
Python one-liner (322 caracteres)
print(lambda l:(lambda s:''/n''.join(['' ''.join(x) for x in zip(*[l[c].split(''/n'')
for c in s])])))(dict(zip(''0123456789abcdef'', ''eJxdjrEBwDAIw3au0Ac9iUd0fJM2DTQD''
''g5ExJgkxTOMKYIzPDDUYORlNsZ3zppwuXsqt/pmmjVmZ/nH6M+9BTXZvU8Umg9fd03SOgvPw==''
.decode(''base64'').decode(''zlib'').split(''/n//n''))))(__import__(''sys'').argv[-1]
.lower())
La mayor parte del tiempo se debe a que soy flojo y uso zlib y base64 builtins para la tabla de búsqueda. Ejecútelo desde la línea de comandos de esta manera:
$ python golf.py fedcba9876543210
Scala, 234 bytes
val a=Seq("|_|"," _ "," |","| |"," _|","| ","|_ "," ")
val m=argv(0).toLowerCase.map(_-''0'').map(i=>if(i<10)i else i-39)
for(s<-Seq(0,16,32))
println(m.map(i=>a("171171111117171132440662000654660264240204306065"(i+s)-''0'')).mkString)
El código es bastante directo: los 9 segmentos posibles se empaquetan en una matriz y se mapean entre el número hexadecimal y la posición. Probablemente, podría estar mejor empaquetado.
El código para calcular números mágicos:
val s = " _ _ *all numbers in one line here* |_||_ | "
val gl = (0 to s.size / 3-1).map(c => s.substring(c*3, c*3+3 ))
// gl now contains flat list of string of 3 chars each
val arr=gl.toSet.toArray // remove duplicates
// for each segment string find corresponding packed index
val n = gl.map( arr indexOf _).mkString
como resultado, n es el número mágico, arr es la matriz de cadenas
Windows PowerShell, 157
$i=[char[]]"$input"
''☺ ☺☺ ☺☺☺☺☺☺ ☺ ☺☺'',''♠☻♥♥♦♣♣☻♦♦♦♣•♥♣♣'',''♦☻♣♥☻♥♦☻♦♥♠♦♣♦♣•''|%{$c=$_
""+($i|%{(''···0·_·0··|0·_|0|_|0|_·0|·|0|··''-split0)[$c[("0x$_"|iex)]]})}
dc - 172 caracteres
Un poco tarde pero una dc
entrada, casi a la especificación: solo acepta números en mayúsculas, es decir, [0-9A-F] y puede imprimir 0 extra al comienzo. De todos modos, aquí está:
16iD9B4FE55FFBDFFA5BF5BAB774977sK
[ ][ _ ][ |][ _|][| ][|_ ][| |][|_|]8[1-ds_:al_d0<L]dsLx
?dsNZdsZ
40sr[[1-dlNr10r^/10%80r^lKr/80%lr/8%;aPd0<L]dsLxAP]dsAx
lZ8srlAxlZ1srlAx
Una pequeña explicación (no se requieren saltos de línea):
La constante 0xD9B4FE55FFBDFFA5BF5BAB774977 codifica cada dígito en 7 bits, por ejemplo, el número ''4'' se codifica como 0 111 010, lo que significa que utiliza la cadena ''0'' para la parte superior ('' ''), la cadena 7 para la mitad (''
|_|
'') y la cadena 2 para el fondo ('' |
'').
La segunda línea define las cadenas y las almacena en la matriz ''a''
La tercera línea maneja la entrada y verifica cuánto tiempo dura el número.
La cuarta línea hace el cálculo. Creó la "subrutina" A y la ejecutó para la primera línea. La subrutina extrae el dígito apropiado ( 1-dlNr10r^/10
), luego extrae los datos de codificación de 7 bits ( 80r^lKr/80%
), luego toma la parte correspondiente para la línea específica ( lr/8%
) carga la cadena y la imprime ( ;aP
) luego pasa por todos los dígitos ( d0<L
)
La última línea hace lo mismo para las líneas 2 y 3 de la pantalla.
JavaScript, 309 304 bytes.
Requiere que no se agreguen funciones de prototipo a String / Array.
function d(b){r="";o=''î$º¶tÖÞ¤þöü^Ê>ÚØ''.split("");p=b.split(r);a=[" 0 ",
"132","465"];c="036";for(k in a){for(var e in p)for(var f in a[k])r+=(U=
a[k][f])==" "?" ":(y=((Q=o[parseInt(p[e],16)].charCodeAt().toString(2))
.length==6?"00"+Q:Q.length==7?0+Q:Q)[U])==0?" ":c.indexOf(U)>-1?"_":"|";
r+="/n"}return r}
Caso de prueba (formateo debido a la primera "
marca de una cadena:
d("0123456789abcdef");
" _ _ _ _ _ _ _ _ _ _ _ _
| | | _| _||_||_ |_ ||_||_||_||_ | _||_ |_
|_| ||_ _| | _||_| ||_| _|| ||_||_ |_||_ | "
C (170 caracteres)
i,j;main(c,s){char**r=s,*p=*++r;for(;i<3;)j--?putchar(!p[-1]?p=*r,++i,j=0,10:
"##3#3133X=W.<X/`^_G0?:0@"[i*8+c/2]-33>>c%2*3+j&1?"|_"[j&1]:32):(j=3,c=*p++&31,
c-=c>6?10:1);}
Esto toma la cadena de entrada como un argumento de línea de comandos. La conversión para usar stdin sería un personaje más:
i,j;main(c){char s[99],*p=s;for(gets(s+1);i<3;)j--?putchar(!*p?p=s,++i,j=0,10:
"##3#3133X=W.<X/`^_G0?:0@"[i*8+c/2]-33>>c%2*3+j&1?"|_"[j&1]:32):(j=3,c=*++p&31,
c-=c>6?10:1);}
La versión stdin puede aceptar hasta 98 caracteres de entrada. Por supuesto, más que floor(terminalWidth / 3)
provocará un ajuste de línea confuso.
La salida de cada carácter se trata como una cuadrícula de 3x3, donde las celdas en cada fila son los segmentos. Un segmento está "encendido" o "apagado". Si un segmento está "encendido", un ''|''
o se emite un ''_''
, dependiendo de la posición. Si está apagado, se genera un espacio. La matriz de caracteres es una matriz de bits que determina si cada segmento está activado o desactivado. Más sobre eso después del código:
i,j; /* Loop variables. As globals, they''ll be initialized to zero. */
main(c,s){
/* The signature for main is
*
* main(int argc, char **argv)
*
* Rather than add more characters for properly declaring the parameters,
* I''m leaving them without type specifiers, allowing them to default to
* int. On almost all modern platforms, a pointer is the same size as
* an int, so we can get away with the next line, which assigns the int
* value s to the char** variable r.
*/
char**r=s,*p=*++r;
/* After coercing the int s to a char** r, offset it by 1 to get the
* value of argv[1], which is the command-line argument. (argv[0] would
* be the name of the executable.)
*/
for(;i<3;) /* loop until we''re done with 3 lines */
j--?
/* j is our horizontal loop variable. If we haven''t finished a
* character, then ... */
putchar( /* ...we will output something */
!p[-1]? /* if the previous char was a terminating null ... */
p=*r,++i,j=0,10
/* ... reset for the next row. We need to:
*
* - reinitialize p to the start of the input
* - increment our vertical loop variable, i
* - set j to zero, since we''re finished with this
* "character" (real characters take 3 iterations of
* the j loop to finish, but we need to short-circuit
* for end-of-string, since we need to output only one
* character, the newline)
* - finally, send 10 to putchar to output the newline. */
:"##3#3133X=W.<X/`^_G0?:0@"[i*8+c/2]-33>>c%2*3+j&1?
/* If we haven''t reached the terminating null, then
* check whether the current segment should be "on" or
* "off". This bit of voodoo is explained after the
* code. */
"|_"[j&1]:32
/* if the segment is on, output either ''|'' or ''_'',
* depending on position (value of j), otherwise,
* output a space (ASCII 32) */
)/* end of putchar call */
:(j=3,c=*p++&31,c-=c>6?10:1);
/* this is the else condition for j--? above. If j was zero,
* then we need to reset for the next character:
*
* - set j to 3, since there are three cells across in the grid
* - increment p to the next input character with p++
* - convert the next character to a value in the range 0–15.
* The characters we''re interested in, 0–9, A–F, and a–f, are
* unique in the bottom four bits, except the upper- and
* lowercase letters, which is what we want. So after anding
* with 15, the digits will be in the range 16–25, and the
* letters will be in the range 1–6. So we subtract 10 if
* it''s above 6, or 1 otherwise. Therefore, input letters
* ''A''–''F'', or ''a''–''f'' map to values of c between 0 and 5,
* and input numbers ''0''–''9'' map to values of c between
* 6 and 15. The fact that this is not the same as the
* characters'' actual hex values is not important, and I''ve
* simply rearranged the data array to match this order.
*/
}
La matriz de caracteres describe las cuadrículas de caracteres. Cada carácter en la matriz describe una fila horizontal de la grilla de salida para dos caracteres de entrada. Cada celda de la cuadrícula está representada por un bit, donde 1
significa que el segmento está "encendido" (por lo que se emite un ''|''
o un ''_''
, según la posición), y 0
significa que el segmento está "apagado".
Se necesitan tres caracteres en la matriz para describir toda la cuadrícula para dos caracteres de entrada. Los tres bits más bajos de cada carácter en la matriz, bits 0-2, describen una fila para el carácter de entrada par de los dos. Los siguientes tres bits, bits 3-5, describen una fila para el carácter de entrada impar de los dos. Los bits 6 y 7 no están en uso. Esta disposición, con un desplazamiento de +33, permite que todos los caracteres de la matriz sean imprimibles, sin códigos de escape ni caracteres que no sean ASCII.
Jugué con varias codificaciones diferentes, incluyendo poner los bits de los 7 segmentos de un personaje de entrada en un personaje de la matriz, pero encontré que este es el más corto. Si bien este esquema requiere 24 caracteres en la matriz para representar los segmentos de solo 16 caracteres de entrada, otras codificaciones requerían el uso de caracteres que no sean ASCII (lo que como era de esperar causó problemas cuando utilicé esto en mi respuesta de golf Morse Code ), muchos códigos de escape y / o código de decodificación complejo. El código de decodificación para este esquema es sorprendentemente simple, aunque aprovecha al máximo la precedencia del operador de C para evitar tener que agregar ningún paréntesis.
Vamos a dividirlo en pequeños pasos para entenderlo.
"##3#3133X=W.<X/`^_G0?:0@"
Esta es la matriz codificada. Tomemos el caracter apropiado para decodificar.
[i*8
Los primeros 8 caracteres describen la fila superior de segmentos, los 8 siguientes describen la fila central de segmentos, y los 8 últimos describen la fila inferior de segmentos.
+c/2]
Recuerde que, en este punto, c contiene un valor de 0 a 15, que corresponde a una entrada de ABCDEF0123456789, y que la matriz codifica dos caracteres de entrada por carácter codificado. Así que el primer carácter de la matriz, ''#''
, contiene los bits de la fila superior de ''A'' y de ''B'', el segundo carácter, también ''#''
, codifica la fila superior de ''C'' y ''D'' , y así.
-33
La codificación da como resultado varios valores que están por debajo de 32, lo que requeriría códigos de escape. Este desplazamiento lleva cada carácter codificado al rango de caracteres imprimibles sin relieve.
>>
El operador de desplazamiento a la derecha tiene una prioridad menor que los operadores aritméticos, por lo que este cambio se realiza al personaje después de restar el desplazamiento.
c%2*3
c%2
evalúa a cero para los números pares, y a uno para los números impares, por lo que cambiaremos a la derecha por tres para los caracteres impares, para obtener los bits 3-5, y no cambiaremos para los caracteres pares, proporcionando acceso a los bits 0-2. Aunque preferiría usar c&1
para la verificación par / impar, y eso es lo que uso en cualquier otro lado, el operador &
tiene una precedencia demasiado baja para usar aquí sin agregar paréntesis. El operador %
tiene la precedencia correcta.
+j
Cambie por j
bits adicionales para obtener el bit correcto para la posición de salida actual.
&1
El operador bit a bit tiene una precedencia menor que los operadores aritméticos y los operadores de desplazamiento, por lo que esto probará si el bit cero se establece después de que el desplazamiento haya llevado el bit relevante al bit cero.
?
Si el bit cero está establecido ...
"|_"
... muestra uno de estos personajes, elegido por ...
[j&1]
... si nuestra variable de ciclo horizontal es par o impar.
:32
De lo contrario (el bit cero no está configurado), salida 32 (carácter de espacio).
No creo que pueda recortar esto mucho más, si es que hay alguno, y ciertamente no lo suficiente como para superar la entrada perl de Hobbs .
Python, 188 caracteres en total
No he analizado demasiado las otras soluciones, pero estoy seguro de que todavía hay mucho por mejorar.
n=int(raw_input(),16)
O=[""]*3
while n:O=["".join(" |_"[(m>>n%16*3+i&1)*(i%2+1)]for i in[2,1,0])+o
for o,m in zip(O,[0x482092490482,0xd9cdff3b76cd,0x9bef5f3d978f])];n>>=4
print"/n".join(O)
Bueno, es difícil superar un lenguaje especializado como Perl. Sin embargo, aquí está la versión de Python en 160 bytes :
i=input().lower()
for x in['' #_ 14bd# '',''| 1237d#_ 017c#| 56bcef'',''| 134579#_ 147af#| 2cef'']: print('' ''.join(''''.join(y[j in y]for y in x.split(''#''))for j in i))
La versión sin código:
input_ = input().lower()
for magic in ['' #_ 14bd# '',
''| 1237d#_ 017c#| 56bcef'',
''| 134579#_ 147af#| 2cef'',
]:
# We have three lines, so x iterates over 3 magic strings.
print('' ''.join(
# This is the cycle iterating over digits.
''''.join(
# For each line and digit we need to print several
# letters. To do this, we break a magic string into
# 3 chunks. A chunk usually contains digits that
# *don''t* have an element there.
chunk[digit in chunk]
# For example, lower right chunk y="| 2cef". For digits
# 2, c, e, f, there should be " ", for all others there
# should be "|". So for digits 2, c, e, f, `j in y` returns
# False and indexes y[0], for other digits it indexes y[1].
for chunk in magic.split(''#''))
for digit in input_))
El mío no es corto, pero fue divertido de hacer:
~ dlamblin$ ./7seg 31337aAbcdeF
_ _ _ _ _ _ _ _ _
_| | _| _| ||_||_||_ | _||_ |_
_| | _| _| || || ||_||_ |_||_ |
#include <stdio.h>
#define P(x) fputs(x,stdout)
#define Z "/33[3D/33[B"
#define a " " Z
#define s " _ " Z
#define d " |" Z
#define f " _|" Z
#define g "| " Z
#define h "| |" Z
#define j "|_ " Z
#define k "|_|" Z
int main(int argc, char** argv){
char m=0,n,*b[]={s h k,a d d,s f j,s f f,a k d,s j f,s j k,s d d,s k k,s k d,
"","","","","","","",
s k h,a j k,s g j,a f k,s j j,s j g};
P("/n/n/n/33[3A");
while (argc>1&&0!=(n=argv[1][m++])){
P(b[n>96?n-80:n-48]);P("/33[3A/33[3C");
}
P("/n/n/n");
}
Puede guardar un par de caracteres eliminando algunas líneas nuevas, pero no me importa. Eso es 500 caracteres, o 482 si saca líneas nuevas y argc>1&&
Requiere soporte de código de escape VT100 y no hará más de 26 caracteres de salida en un terminal de 80 columnas.
PD: Me gustaría ver a más personas mostrar su resultado.
Hombre ... no puede vencer al perl. Aquí hay algunos py3k en 163 caracteres.
i=input()
[print(''''.join('' | _ _|| | ||_ |_|''[(7&(d>>l))*3:][:3]for d
in[255&0xb4b61fa637bdbbbf89b7b3399b9e09af>>int(x,16)*8 for x in i]))for
l in[6,3,0]]
Explicación. Primero, aquí está lo que parecía completamente sin optimizar:
# segment positions, easily understandable as octal. first digit is top row
# last digit is bottom row. high bit is first column, low bit last.
a=[0o257, 0o011, 0o236, 0o233,
0o071, 0o263, 0o267, 0o211,
0o277, 0o273, 0o275, 0o067,
0o246, 0o037, 0o266, 0o264]
# and the corresponding segments:
# 421 421 421 421 421 421 421 421
b=['' '', '' |'', '' _ '', '' _|'', ''| '', ''| |'', ''|_ '', ''|_|'']
# function to look for the proper segment for a decoded digit:
def lookup(digit, line):
return b[ 7& (digit>>(6-line*3))]
#function to encode an ascii hex string into coded form suitible for
#above function
def code(i):
return [a[int(x,16)] for x in i]
def fmt(i):
return ''/n''.join(''''.join(lookup(d,l) for d in code(i)) for l in [0,1,2])
i = input()
print(fmt(i))
Luego voy a buscar maneras de empacar los datos. Primero puedo transformar a un entero grande, largo, el último elemento primero, 8 bits a la vez. Eso produce, en octal: 0o2645541764615736673577046675463463347404657
. escrito en hexadecimal, eso es 0xb4b61fa637bdbbbf89b7b3399b9e09af
, 90 caracteres más cortos que la lista de octals. Para usarlo, debes reescribir el código, por supuesto. Eso parece como
def code_a_8(i):
return [255&a_8>>int(x,16)*8 for x in i]
b
puede concatenarse, ''''.join(b)
es 26 caracteres, incluidas las comillas. la función de búsqueda también debe cambiar para admitir esto.
def lookup_b_cat(d, l):
return b_cat[(7&(d>>6-l*3))*3:][:3]
A continuación, elimino toda la sintaxis innecesaria al plegar funciones y constantes en la expresión, y eso es todo.
También es posible ajustar un poco la impresión. En lugar de unir las líneas, simplemente imprímalas inmediatamente. esto da como resultado una fmt()
modificada fmt()
:
def fmt_print(i):
[print(''''.join(lookup(d,l) for d in code(i))) for l in [0,1,2]]
Mi primer código de golf. 279 caracteres que no son de espacios en blanco, 433 espacios incluidos. Estoy seguro de que podría ser más corto en Python.
Pitón
import sys
w = sys.stdout.write
i = raw_input()
d = [111,9,94,91,57,115,119,73,127,123,125,55,102,31,118,116]
p = ['' _ '',''|'',''_'',''|'',''|'',''_'',''|'']
j = 0
for r in range(3):
for c in i.lower():
for n in range(3 if r else 1):
s = p[j+n]
if (1<<6-j-n) & d[ord(c)-(ord(''0'') if c.isdigit() else ord(''a'')+6)]:
w(s)
else:
w('' ''*len(s))
j += n+1
w(''/n'')
Caracteres de Javascript 333 cuando están embalados
s=" ";
function r(p)
{
if(t[p]=="0")
return s;
return "_|_||_|".split("")[p];
}
function g(w){
a="";b=a;c=a;
z=[];
for(x=0;x<w.length;x++){
t=("000"+parseInt("6F095E5B397377497F7B7D37661F7674".substr(parseInt(w.substr(x,1),16)*2,2),16).toString(2)).slice(-7).split("");
a+=s+r(0)+s+s;
b+=r(1)+r(2)+r(3)+s;
c+=r(4)+r(5)+r(6)+s;
}
return a+"/n"+b+"/n"+c;
}
alert(g("0123456789deadbeef"));
Ejecutable COM: 102 bytes
Ensamble lo siguiente usando A86 (esta es la versión original, más grande):
dd 0801E8Ah,0BD80C380h,03B50154h,0D789D58Ah,0B20082BEh,077F33B03h,0C048A29h,0149F0420h
dd 020AD431h,088C402C4h,01468BC1h,0F8C1E0D3h,046220Fh,0AA036E8Dh,0DD75CAFEh,04609ED83h
dd 0C583D1EBh,0D0AB809h,075CDFEABh,0AA24B0C3h,021CD09B4h,05F0000C3h,020B7EBh,8EFB7C00h
dd 07C3EF75Fh,0BF7CF9E4h,0B6DE5FA2h
dw 0F47Ch
db 0DFh
Editar:
El problema de DosBox es probablemente la forma en que el programa asume los valores de registro en la puesta en marcha. De todos modos, aquí está la fuente modificada que se ensambla a 102 bytes y debería funcionar con DosBox:
mov bp,d1
mov ch,3
mov dx,ds ; if you want to use dos box, put "mov dx,08000h" here instead, it might fix the problem
mov di,dx
l4: mov si,082h
l3: mov bl,3
cmp byte ptr [si],0dh
je l5
mov cl,[si]
cmp cl,40h
jle l2
add cl,9
l2: and cl,0fh
l1: mov ax,word ptr [bp+1]
shl ax,cl
sar ax,15
and al,byte ptr [bp]
add bp,3
stosb
dec bl
jnz l1
sub bp,9
inc si
jmp l3
l5: add bp,9
mov ax,0d0ah
stosw
dec ch
jnz l4
mov al,''$''
stosb
mov ah,9
int 21h
d1: ret
dw 0
db ''_''
dw 01011011111101011xb
db '' ''
dw 0
db ''|''
dw 01000111011111011xb
db ''_''
dw 00011111011110111xb
db ''|''
dw 01111100111100100xb
db ''|''
dw 01010001010111111xb
db ''_''
dw 01011011011011110xb
db ''|''
dw 01101111111110100xb
¡Gracias a ephemient por un par de ajustes!
Haskell, 259 caracteres.
¿Haskell es malo para el golf o soy yo (mi primer golf)?
import Char
i=iterate
d b=map(`mod`b).i(`div`b)
z _ 0='' ''
z a 1=a
r=take 3
main=
getLine>>=
putStr.unlines.foldl1(zipWith(++)).
map(r.map r.i(drop 3).take 9.zipWith z(cycle"|_|").(0:).d 2.
(d 256(0xddfd91edcd9cd97990f5*2^384+0x2d6df865ecbd*(2^520+2^776))!!).ord)
(dividir principal a líneas para legibilidad)
Compila con -Wall y se puede entender; no muy corto (~ 400 caracteres). En una implementación seria, sacaría el índice char-> de la parte de salida (y almacenaría los índices en un búfer en lugar de los caracteres). Global r se inicializa a 0, que no sería si fuera un local en main.
#include <stdio.h>
typedef char const* R;
R _=" _ ",S=" ",I=" |",J=" _|",L="|_ ",U="|_|",N="| |",C="| ";
R s[][16]={
{_,S,_,_,S,_,_,_,_,_,_,S,_,S,_,_},
{N,I,J,J,U,L,L,I,U,U,U,L,C,J,L,L},
{U,I,L,J,I,J,U,I,U,J,N,U,L,U,L,C}};
int r,c,i;
int main(){
char b[999];
scanf("%s",b);
for(;r<3;++r)
for(c=0;;) {
i=b[c++]-''0'';
if (i>16) i-=7;
if (i>15) i-=32;
if (i<0||i>15){putchar(''/n'');break;}
printf("%s",s[r][i]);
}
return 0;
}