Marcar Codificador de semáforo

12

Su objetivo es escribir un codificador de semáforo de bandera , que convertirá una oración dada en los caracteres de semáforo de bandera correspondientes, de acuerdo con el sistema de semáforo descrito en Wikipedia .

Suponga que la entrada es una oración única proporcionada a través de stdin (o equivalente). Su salida debe ser una serie de caracteres de semáforo, con cada fila representando una palabra de la oración. Solo necesita tratar con el alfabeto (AZ) y debe ignorar todos los demás caracteres que no sean espacios, pero debe poder manejar tanto mayúsculas como minúsculas. Su salida puede contener espacios en blanco adicionales.

Los caracteres del semáforo deben mostrarse como un cuadrado de 3x3, con una posición Oen el medio y la bandera representada por los caracteres | - / \. Cada carácter de semáforo debe estar separado de los caracteres adyacentes por un espacio, y cada fila debe estar separada por una línea en blanco. No se preocupe por ajustar las palabras que pueden ser demasiado largas para su pantalla; pretenda que sus líneas tienen una longitud infinita.

Entrada de muestra:

abcdefg hijklmn opqrstu vwxyz

Salida de muestra:

        \    |    /
 O  -O   O   O   O   O-  O
/|   |   |   |   |   |   |\

    \    |   |    /
-O   O   O-  O   O   O-  O
/   /       /   /   /   / \

\    |    /         \|  \ /
-O  -O  -O  -O- -O   O   O
                  \ 

 |    /   / \ 
 O   O-  O   O-  O-
  \       \       \

Entrada de muestra:

This is Code Golf.

Salida de muestra:

\|      \ 
 O  -O   O  -O 
    /   /     \

\      
 O  -O 
/     \

\   \    |    /
 O  -O   O   O 
 |       |   |

    \     /  
 O  -O   O   O-
 |\     /    |

Como se trata de , gana la solución más corta.

migimaru
fuente
1
kolmogorov-complejidad ? Me parece que fundamentalmente se trata de comprimir una tabla de búsqueda.
Peter Taylor
@ Peter Taylor Sí, probablemente sea una buena idea agregar esa etiqueta. Gracias.
migimaru
and each row must be separated by a blank line=> cada palabra significa, ¿no?
Usuario desconocido el
1
Antes de leer este rompecabezas, pensé erróneamente que tenía que ver con los semáforos en el sentido de la programación. ¡Jajajajajja!
Thomas Eding
@user unknown Estaba usando una fila allí para referirme a una fila de caracteres de semáforo . Quizás el uso de la palabra hubiera sido una mejor opción.
migimaru

Respuestas:

5

Perl, 282 264 251 247 245 243 241 240 236 233 229 227 220 218 216 214 caracteres

$_=lc<>;map{y/a-z//cd;y/a-z/`HABDP\xc0(!\x12"$0\xa0\t\n\f\30\x88\3\5\x82\24\x84\21\x90/;@a=($/)x4;map{$s=ord;$a[$_/3].=substr" \\|/-O-/|\\",$_==4||$s>>$_-($_>4)&1?$_+1:0,1for 0..8;$_.=" "for@a}split//;print@a}split

Con algunos saltos de línea prettifying:

$_=lc<>;
map{
y/a-z//cd;
y/a-z/`HABDP\xc0(!\x12"$0\xa0\t\n\f\30\x88\3\5\x82\24\x84\21\x90/;
@a=($/)x4;
map{
$s=ord;
$a[$_/3].=substr" \\|/-O-/|\\",$_==4||$s>>$_-($_>4)&1?$_+1:0,1for 0..8;
$_.=" "for@a
}split//;
print@a}split

Me tomó un tiempo hacer que esto funcione (mi primer intento de respuesta de Perl). Se basa en una idea similar a muchas de las otras respuestas. Cada bandera puede estar en una de 8 posiciones, hay dos banderas y las dos banderas nunca pueden estar en la misma posición. Esto significa que puedo codificar la posición de ambos indicadores en un byte, lo que también significa que puedo traducir directamente de un personaje a su codificación utilizando la y///función de Perl (¿operador?). Entonces:-

a = 01100000 96 = `
b = 01001000 72 = H
c = 01000001 65 = A
d = 01000010 66 = B
e = 01000100 68 = D
f = 01010000 80 = P
etc...

Por lo tanto:

y/a-z/`HABDP..../;

He escapado de algunos de los caracteres que están fuera del rango normal utilizado para facilitar la copia y el pegado del programa, pero estoy bastante seguro de que podría escribir un programa para reemplazar los códigos de escape con los caracteres mismos, salvándome Aproximadamente 30 caracteres.

Gareth
fuente
6

Pitón, 244 238 233 232

e='abhioptuwycdjmnsqxzfgvklebr'
for w in raw_input().split():
 for i in 0,3,6,9:print' '.join(''.join((' '+'\|/-O-/|\ '[j])[`j`in'4'+'6736031025071568328578162735'[e.find(c):][:2]]for j in range(i,9)[:3])for c in w if c.lower()in e)

Utiliza un truco mío favorito: la codificación de una sola pista. He etiquetado los bits del semáforo (bits)

\|/     012
- -  -> 3 5
/|\     678

para obtener la siguiente tabla de los bits que se producen para cada letra:

0: ciotuy
1: djkptv
2: elquwx
3: bhopqrs
5: fjmrwyz
6: ahiklmn
7: abcdefg
8: gnsvxz

cada letra aparece exactamente dos veces en la tabla, ya que el señalero tiene dos brazos. Luego, veo esto como un gráfico en las letras az, con bordes entre letras que comparten sbits, con los bordes etiquetados de acuerdo con el sbit compartido. Lo ideal sería encontrar una ruta de Hamilton a través de este gráfico, de modo que los bordes posteriores no tengan la misma etiqueta. No existen tales rutas ... así que notarás que la variable econtiene la letra bdos veces.

Con mi camino casi Hamilton e, construyo una serie dde etiquetas sbit utilizadas en el recorrido de e. Luego, para averiguar dónde colocar sus brazos, el encargado de la señal solo necesita encontrar la letra deseada en la siguiente tabla práctica

abhioptuwycdjmnsqxzfgvklebr
6736031025071568328578162735

de donde sus brazos van en la posición directamente debajo, y debajo y a la derecha de la carta.

boothby
fuente
No podía lograr que esto funcionara con ideone hasta que me cambiara to_lower()a lower(). Además, dio un error cuando intenté darle una entrada no alfabética.
migimaru
4

Scala, 272 caracteres

println(readLine.filter(c=>c.isLetter||c==' ').toLowerCase.split(" ").map{_.map(q=>("    O    "/:("^@a,6Tr?W*+5Sq9(2Pn%/-47MU"(q-'a')-27+""))((g,x)=>g.updated(x-'0',"\\|/-O-/|\\"(x-'0'))).grouped(3).toList).transpose.map(_.mkString(" ")).mkString("\n")}.mkString("\n\n"))

Sin golf (bueno, menos golfizado):

println(
  readLine.filter(c => c.isLetter || c==' ').
  toLowerCase.
  split(" ").
  map{ s =>
    val lookup = "^@a,6Tr?W*+5Sq9(2Pn%/-47MU".map(c => (c-27).toString)
    s.map(q =>
      ("    O    " /: lookup(q-'a')){(g,x) => 
        g.updated(x-'0', "\\|/-O-/|\\"(x-'0'))
      }.grouped(3).toList
    ).transpose.map(_.mkString(" ")).mkString("\n")
  }.mkString("\n\n")
)
Rex Kerr
fuente
2

Rubí, 287 caracteres.

gets.split.map{|w|puts (0..2).map{|l|w.chars.map{|c|(' '*576+'CAEAEADBCAF DAEBDACAAAI EAFADACAABG BAEAFEL A_ FACABADADAAG AAFBADQ AGX GAFADABAAAAF'.split.zip('\\|/-o-/|\\'.chars).map{|a,c|(a.chars.zip([' ',c]*9).map{|x,z|[z]*(x.ord-64)}.flatten)}.transpose*''*2)[c.ord*9+3*l,3]}*' '},''}

La entrada debe darse en STDIN.

Howard
fuente
1

Scala 494 sin líneas nuevas 520 con líneas nuevas:

def k(i:Int,d:Int=0):(Int,Int)=if(i<(7-d))(d,i+1)else k(i-(7-d),d+1)
def t(i:Char)=(if(i=='y')i-4 else
if(i=='z')i+2 else
if(i=='j')i+14 else
if(i>='v')i+3 else
if(i>'i')i-1 else i)-'a'
def q(p:(Int,Int),i:Int,c:Char)=if(p._1==i||p._1+p._2==i)""+c else" "
def g(r:Int,c:Char)={val p=k(t(c.toLower))
print((r match{case 1=>q(p,3,'\\')+q(p,4,'|')+q(p,5,'/')
case 2=>q(p,2,'-')+"o"+q(p,6,'-')
case 3=>q(p,1,'/')+q(p,0,'|')+q(p,7,'\\')})+" ")}
for(w<-readLine.split(" ")){println;for(r<-(1 to 3)){w.map(c=>g(r,c));println}}

sin golf:

def toClock (i: Int, depth: Int=0) : (Int, Int) = {
  if (i < (7 - depth)) (depth, i+1) else toClock (i - (7-depth), depth + 1)}

def toIdx (i: Char) = {
 (if (i == 'y') i - 4  else 
  if (i == 'z') i + 2  else 
  if (i == 'j') i + 14 else 
  if (i >= 'v') i + 3 else 
  if (i > 'i') i - 1 else i ) - 'a'}

def p2c (pair: (Int, Int), i: Int, c: Char) = {
 if (pair._1 == i || pair._1 + pair._2 == i) ""+c else " "
}

def printGrid (row: Int, c: Char) = {
  val idx = toIdx (c.toLower)
  val pair = toClock (idx)
  row match {
    case 1 => { print(
      p2c (pair, 3, '\\') + 
      p2c (pair, 4, '|') + 
      p2c (pair, 5, '/') + " ")
    }
    case 2 => { print(
      p2c (pair, 2, '-') + "o" + 
      p2c (pair, 6, '-') + " ")
    }
    case 3 => { print(
      p2c (pair, 1, '/') + 
      p2c (pair, 0, '|') + 
      p2c (pair, 7, '\\') + " ")
    }
  }
}

val worte = "This is Code Golf"
(1 to 3).map (row => {worte.map (c => printGrid (row, c));println})

Explicación:

Observé un patrón de reloj, pero no con 12 horas, sino con 8. Y la hora de inicio es 0, donde son las 6 en punto, y a, b, c son los primeros códigos, con la primera (una) bandera en el sur.

Como las banderas 1 y 2 no se pueden distinguir, podemos ordenar todas las combinaciones con el número más bajo para la primera bandera primero. Desafortunadamente, el buen orden desde el principio se ve alterado, cuando j no sigue a i, pero k, l, m, y luego se vuelve un desastre.

Por lo tanto, reorganizo mis claves para el mapeo:

val iis = is.map {i => 
  if (i == 'y') i - 4  else 
  if (i == 'z') i + 2  else 
  if (i == 'j') i + 14 else 
  if (i >= 'v') i + 3 else 
  if (i > 'i') i - 1 else i }.map (_ - 'a')

iis.zipWithIndex .sortBy (_._1) .map (p => (p._1, ('a' + p._2).toChar))

Vector((97,a), (98, b), (99, c), (100,d), (101,e), (102,f), (103,g), 
      (104,h), (105,i), (106,k), (107,l), (108,m), (109,n), 
      (110,o), (111,p), (112,q), (113,r), (114,s), 
      (115,t), (116,u), (117,y), -------
      -------  (120,j), (121,v), 
      (122,w), (123,x), 
      (124,z))

Si restamos 'a' de cada personaje, obtenemos los números de (0 a 7 + 6 + 5 + ... + 1). Podemos mapear los números de una cuadrícula de caracteres

3 4 5   \ | /            |
2   6   - o -    - o   - o 
1 0 7   / | \    (2, ) (2,2)

Un par de dos números puede asignar dos banderas, donde el primer número es el índice de 0 a 6 para la primera bandera, y la segunda bandera no es un número del 1 al 7 para la segunda bandera, sino para la distancia desde el primero a la segunda bandera. (2,2) significaría que la primera bandera es hacia el OESTE, y la segunda es dos pasos en sentido horario desde allí, hacia el NORTE.

def toClock (i: Int, depth: Int=0) : (Int, Int) = {
  if (i < (7 - depth)) (depth, i+1) else toClock (i - (7-depth), depth + 1)}

Vector( (0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), 
    (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), 
    (2,1), (2,2), (2,3), (2,4), (2,5), 
    (3,1), (3,2), (3,3), 
           (4,2), (4,3), 
    (5,1), (5,2), 
    (6,1))
usuario desconocido
fuente
No sé mucho sobre Scala. ¿Hay alguna manera de probar esto en ideone? Intenté envolverlo en un object Main extends Applicationbloque, pero eso no parece ser suficiente.
migimaru
IDEONE necesita una clase llamada Main, si no recuerdo mal, un método main, tal vez debería extender la aplicación (para scala-2.9, en lugar de la aplicación (-2.8)), ¿y se lee desde stdin? En simplyscala puede probar el código de manera más simple. Si reemplaza readLineen la última línea "readLine", debería funcionar (el código es compatible con 2.8).
usuario desconocido
¡Gracias! No conocía simplemente la escala, eso hace las cosas mucho más fáciles.
migimaru
Si necesita el enlace nuevamente: ya inserté el enlace en algún lugar del meta, donde se recopilan esas cosas.
usuario desconocido el
¿Esto maneja mayúsculas?
Thomas Eding
1

Haskell 331 357 339 caracteres

Golfizado:

import Data.Char
t[x,y]=q[x,mod(y+1)8]
q z@[x,y]|x==y=[x+1,y+2]|0<1=z
x%y=[x,y]
c 65=0%1
c 74=6%4
c 75=1%4
c 79=2%3
c 84=3%4
c 86=4%7
c 87=5%6
c 89=3%6
c 90=6%7
c x=t$c$pred x
_!9='O'
c!n|n`elem`c="|/-\\"!!mod n 4|0<1=' '
s x=do n<-[3:4%5,2:9%6,1:0%7];'\n':do c<-x;' ':map(c!)n
main=putStr.s.map(c.ord.toUpper)=<<getLine

Sin golf:

type Clock = [Int]

tick :: Clock -> Clock
tick [h, m] = tick' [h, mod (m + 1) 8]

tick' :: Clock -> Clock
tick' [h, m]
  | h == m = [h + 1, m + 2]
  | otherwise = [h, m]

clock :: Char -> Clock
clock 'a' = [0,1]
clock 'j' = [6,4]
clock 'k' = [1,4]
clock 'o' = [2,3]
clock 't' = [3,4]
clock 'v' = [4,7]
clock 'w' = [5,6]
clock 'y' = [3,6]
clock 'z' = [6,7]
clock c = tick $ clock $ pred c

arm :: Int -> Char
arm 0 = '|'
arm 1 = '/'
arm 2 = '-'
arm 3 = '\\'

drawAt :: Clock -> Int -> Char
drawAt _ 9 = 'O'
drawAt c n = if n `elem` c
  then arm $ n `mod` 4
  else ' '

-- showClock is not in golfed code. Just there for debugging.
showClock :: Clock -> String
showClock c = unlines $ map (map $ drawAt c) [
    [3,4,5]
  , [2,9,6]
  , [1,0,7]
  ]

showClocks :: [Clock] -> String
showClocks cs = unlines $ map (showClocks' cs) [[3,4,5],[2,9,6],[1,0,7]]

showClocks' :: [Clock] -> [Int] -> String
showClocks' cs ns = cs >>= \c -> ' ' : map (drawAt c)

mainx :: IO ()
mainx = putStr . showClocks . map clock =<< getLine

345    \|/                                     \                      
2 6 == -O-          -O          tick  -O   ==   O      tick   O   ==  -O
107    /|\          /                 /        /              |\      /
             [1,2] or [2,1]    tick [1,2] == [1,3]     tick [0,7] == [1,2]

La codificación es [hour, minute]donde los relojes tienen 8 horas y 8 minutos. Los minutos se mueven más rápido que las horas. Si un reloj marca donde la hora y los minutos serían iguales, agregue 1 a la hora y 2 al minuto también (vea el segundo ejemplo de la marca anterior). Esa es la única forma en que aumentan las horas. Las horas NO aumentan cuando el minuto llega a un minuto arbitrario. Solo cuando los minutos equivalen a horas. En el código sin golf, clockconvierte las letras en relojes que representan el semáforo. La mayoría de los relojes se construyen en función de los tics de los anteriores. El resto está codificado. No hay nada realmente más en el código.

Thomas Eding
fuente
1

Perl, 356 , 275 caracteres

Gran cantidad de caracteres se salvó al reemplazar 'if else' a '? : 'construcción.

@_=split('', $ARGV[0]);for (@_){print eval{/[ciotuy]/ ?'\\':' '}.eval{/[djkptv]/ ?'|':' '}.eval{/[elquwx]/ ?'/':' '}."\n".eval{/[bhopqrs]/ ?'-':' '}."0".eval{/[fjmrwyz]/ ?'-':' '}."\n".eval{/[ahiklmn]/ ?'/':' '}.eval{/[abcdefg ]/ ?'|':' '}.eval{/[gnsvxz]/ ?'\\':' '."\n"};}
zura
fuente
Su código solo parece funcionar para letras minúsculas. Si usa en <>lugar de $ARGV[0]puede tomar la entrada de stdin y usar lcpara convertir todos los caracteres a minúsculas. Esto tiene el beneficio adicional de guardarle 4 caracteres. Tampoco maneja caracteres que no sean del alfabeto, pero podría decirse You only need to deal with the alphabet (A-Z) and should ignore all other non-space charactersque no está muy claro qué hacer con ellos ...
Gareth
No puedo probar el código en este momento, pero parece que el código solo imprime espacios para caracteres no alfa, lo cual está bien.
migimaru
@migimaru Trataré de corregirlo.
zura
@zura Se aceptan espacios de impresión para caracteres que no sean del alfabeto. No necesitas arreglar eso.
migimaru
0

PowerShell , 198 192 191 188 bytes

-split$args|%{$s=$_
"\|/ ciotuy djkptv elquwx","-O- bho-s ^ fjmrwyz","/|\ ahik-n a-g gnsvxz"|%{$f,$p=-split$_
($s|% t*y|%{$c=$_
-join(&{$p|%{" $f"[++$i*($c-match"[$_ ]")]}})})-join' '}
''}

Pruébalo en línea!

La salida contiene una línea de cola vacía.

Menos golfizado:

-split$args|%{
    $string=$_
    "\|/ ciotuy djkptv elquwx",
    "-O- bho-s ^ fjmrwyz",
    "/|\ ahik-n a-g gnsvxz"|%{
        $flags,$patterns=-split$_
        $row=$string|% toCharArray|%{
            $char=$_
            $semaphoreRow=&{   # call the scriptblock in a new scope to reinit $i
                $patterns|%{
                    " $flags"[++$i*($char-match"[$_ ]")]  # return a flag symbol
                }
            }
            -join($semaphoreRow)
        }
        $row-join' '
    }
    ''
}
mazzy
fuente
0

Carbón de leña , 70 bytes

F⪪↧S «Fι«F⪪”↶↖→∧gτ→|⮌!⧴KD✂‖5»⊞H⭆K↧ⅉ&$↥x-#↖x9|²λPe⁸” «P⊗№λκ↷¹»oM³→»⸿M³↓

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

F⪪↧S «

Divida la entrada en minúsculas en los espacios y repita sobre cada palabra.

Fι«

Recorre cada personaje.

F⪪”↶↖→∧gτ→|⮌!⧴KD✂‖5»⊞H⭆K↧ⅉ&$↥x-#↖x9|²λPe⁸” «

Divida la cadena comprimida fjmrwyz gnsvxz abcdefg ahiklmn bhopqrs ciotuy djkptv elquwxen espacios y repita sobre cada grupo de letras.

P⊗№λκ

Si el grupo contiene la letra actual, dibuje una línea en la dirección actual.

↷¹»

Gire 45 ° en sentido horario.

oM³→»

Salida del centro oy pasar a la posición de la siguiente letra.

⸿M³↓

Ir al inicio de la siguiente palabra.

Neil
fuente