Marca codificador de semáforo


12

Seu objetivo é escrever um codificador de semáforo de bandeira , que converterá uma determinada frase nos caracteres correspondentes de semáforo de bandeira, de acordo com o sistema de semáforo descrito na Wikipedia .

Suponha que a entrada seja uma única frase fornecida por meio de stdin (ou equivalente). Sua saída deve ser uma série de caracteres de semáforo, com cada linha representando uma palavra da frase. Você só precisa lidar com o alfabeto (AZ) e deve ignorar todos os outros caracteres que não sejam espaços, mas deve poder manipular letras maiúsculas e minúsculas. Sua saída pode conter espaço em branco extra.

Os caracteres do semáforo devem ser exibidos como um quadrado 3x3, com um Ono meio e as posições de bandeira representadas pelos caracteres | - / \. Cada caractere de semáforo deve ser separado dos caracteres adjacentes por um espaço e cada linha deve ser separada por uma linha em branco. Não se preocupe em agrupar palavras que podem ser muito longas para sua exibição - finja que suas linhas têm um comprimento infinito.

Entrada de amostra:

abcdefg hijklmn opqrstu vwxyz

Saída de amostra:

        \    |    /
 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 amostra:

This is Code Golf.

Saída de amostra:

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

\      
 O  -O 
/     \

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

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

Como se trata de , a solução mais curta vence.


1
complexidade kolmogorov ? Parece-me que fundamentalmente trata-se de compactar uma tabela de pesquisa.
Peter Taylor

@ Peter Taylor Sim, provavelmente é uma boa ideia adicionar essa tag. Obrigado.
migimaru 02/09/11

and each row must be separated by a blank line=> cada palavra significa, não é?
usuário desconhecido

1
Antes de ler este quebra-cabeça, pensei erroneamente que tinha a ver com semáforos no sentido de programação. ¡Jajajajajja!
Thomas Eding

@user unknown Eu estava usando a linha lá para me referir a uma linha de caracteres de semáforo . Talvez usar a palavra fosse uma escolha melhor.
migimaru 02/09/11

Respostas:


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

Com algumas quebras de linha pretextantes:

$_=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

Demorei um pouco para que isso funcionasse (minha primeira tentativa de resposta em Perl). É baseado em uma idéia semelhante a muitas das outras respostas. Cada bandeira pode estar em uma das 8 posições, há duas bandeiras e as duas bandeiras nunca podem estar na mesma posição. Isso significa que posso codificar a posição de ambos os sinalizadores em um byte - o que também significa que posso traduzir diretamente de um caractere para sua codificação usando a y///função Perl (operador?). Então:-

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

Portanto:

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

Eu escapei de alguns dos caracteres que estão fora do intervalo normal usado para facilitar a cópia e a colagem do programa - mas tenho quase certeza de que poderia escrever um programa para substituir os códigos de escape pelos próprios caracteres, me salvando aproximadamente 30 caracteres.


6

Python, 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)

Isso usa um dos meus truques favoritos: codificação de faixa única. Eu rotulei os bits de semáforo (sbits)

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

para obter o seguinte gráfico de quais sbits ocorrem para qual letra:

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

cada letra ocorre exatamente duas vezes no gráfico, uma vez que o sinaleiro tem dois braços. Então, vejo isso como um gráfico nas letras az, com bordas entre letras que compartilham sbits, com as bordas rotuladas de acordo com o sbit compartilhado. Idealmente, eu encontraria um caminho Hamilton através deste gráfico, de modo que as arestas subsequentes não tenham o mesmo rótulo. Nenhum desses caminhos existe ... então você notará que a variável econtém a letra bduas vezes.

Com o meu caminho quase Hamilton e, construo uma matriz dde rótulos de sbit usados ​​na travessia de e. Então, para descobrir onde colocar os braços, o sinaleiro só precisa encontrar a letra desejada na tabela a seguir

abhioptuwycdjmnsqxzfgvklebr
6736031025071568328578162735

de onde seus braços ficam na posição diretamente abaixo e abaixo e à direita da letra.


Não consegui fazer isso rodar em ideone até mudar to_lower()para lower(). Além disso, ocorreu um erro ao tentar fornecer uma entrada não alfabética.
migimaru 02/09/11

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"))

Sem Golfe (bem, com menos golfe):

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")
)

2

Ruby, 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]}*' '},''}

A entrada deve ser fornecida no STDIN.


1

Scala 494 sem novas linhas 520 com novas linhas:

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}}

ungolfed:

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})

Explicação:

Eu observei um padrão de relógio, mas não com 12 horas, mas 8. E Starttime é 0, onde são 6 horas e a, b, c são os primeiros códigos, com a primeira (uma) bandeira no sul.

Como os sinalizadores 1 e 2 são indistinguíveis, podemos classificar todas as combinações com o número mais baixo para o primeiro sinalizador primeiro. Infelizmente, a ordem correta desde o início é perturbada, quando j não segue i, mas k, l, m, e depois fica uma bagunça.

Portanto, reorganizo minhas chaves para o mapeamento:

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))

Se subtrairmos 'a' de todos os caracteres, obteremos os números de (0 a 7 + 6 + 5 + ... + 1). Podemos mapear os números de uma grade de caracteres

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

Um par de dois números pode mapear dois sinalizadores, onde o primeiro número é o índice de 0 a 6 para o primeiro sinalizador e o segundo sinalizador não é um número de 1 a 7 para o segundo sinalizador, mas para a distância do primeiro para o segundo sinalizador. (2,2) significaria, a primeira bandeira é para OESTE, e a segunda é dois passos no sentido horário a partir daí, para o 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))

Eu não sei muito sobre Scala. Existe uma maneira de testar isso em ideone? Tentei envolvê-lo em um object Main extends Applicationbloco, mas isso não parece suficiente.
migimaru 02/09

O IDEONE precisa de uma classe chamada Main, se bem me lembro, um método principal, talvez deva estender o App (para scala-2.9, em vez de Application (-2.8)) - e ele lê a partir de stdin? Na simplyscala, você pode testar o código de maneira mais simples. Se você substituir readLinena última linha por "readLine"ele deve funcionar (o código é compatível com 2.8).
usuário desconhecido

Obrigado! Eu não sabia sobre simplyscala, isso facilita muito as coisas.
migimaru 3/09/11

Se você precisar do link novamente: já inseri o link em algum lugar da meta, onde essas coisas são coletadas.
usuário desconhecido

Isso lida com maiúsculas?
Thomas Eding

1

Haskell 331 357 339 caracteres

Golfe:

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

Ungolfed:

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]

Codificação é [hour, minute]onde os relógios têm 8 horas e 8 minutos. Os minutos se movem mais rápido que horas. Se um relógio marcar onde a hora e o minuto seriam iguais, adicione 1 à hora e 2 ao minuto também (veja o exemplo do segundo tick acima). Essa é a única maneira de aumentar as horas. As horas NÃO aumentam quando o minuto atinge um minuto arbitrário. Somente quando os minutos equivalem a horas. No código não destruído, clocktransforma letras em relógios que representam o semáforo. A maioria dos relógios é construída com base nos tiques dos anteriores. O restante é codificado. Não há realmente nada mais no código.


1

Perl, 356 , 275 caracteres

Um grande número de caracteres foi salvo substituindo 'if else' para '? :' construção.

@_=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"};}

Seu código parece funcionar apenas com letras minúsculas. Se você usar em <>vez de, $ARGV[0]poderá usar lca entrada stdin e usar para converter todos os caracteres em minúsculas. Isso tem o benefício adicional de salvar 4 caracteres. Ele não lida com caracteres não-alfabeto também, mas sem dúvida You only need to deal with the alphabet (A-Z) and should ignore all other non-space charactersnão é muito clara sobre o que fazer com eles ...
Gareth

Não estou conseguindo testar o código no momento, mas parece que o código apenas imprime espaços para caracteres não alfa, o que é bom.
migimaru 8/09/11

@igimaru Vou tentar corrigi-lo.
Zura

@zura Os espaços de impressão para caracteres não alfabéticos são aceitáveis. Você não precisa consertar isso.
migimaru 11/09/11

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' '}
''}

Experimente online!

A saída contém uma linha vazia de cauda.

Menos golfe:

-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' '
    }
    ''
}

0

Carvão , 70 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

F⪪↧S «

Divida a entrada em minúsculas em espaços e faça um loop sobre cada palavra.

Fι«

Faça um loop sobre cada caractere.

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

Divida a sequência compactada fjmrwyz gnsvxz abcdefg ahiklmn bhopqrs ciotuy djkptv elquwxem espaços e faça um loop sobre cada grupo de letras.

P⊗№λκ

Se o grupo contiver a letra atual, desenhe uma linha na direção atual.

↷¹»

Gire 45 ° no sentido horário.

oM³→»

Saída do centro oe vá para a posição da próxima letra.

⸿M³↓

Vá para o início da próxima palavra.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.