Encoder bandiera semaforo


12

Il tuo obiettivo è quello di scrivere un codificatore a semaforo a bandiera , che convertirà una determinata frase nei corrispondenti caratteri a semaforo a bandiera, secondo il sistema dei semafori descritto su Wikipedia .

Supponiamo che l'input sia una singola frase fornita tramite stdin (o equivalente). L'output dovrebbe essere una serie di caratteri semaforo, con ogni riga che rappresenta una parola dalla frase. Devi solo gestire l'alfabeto (AZ) e ignorare tutti gli altri caratteri non spaziali, ma devi essere in grado di gestire sia lettere maiuscole che minuscole. Il tuo output può contenere spazi bianchi extra.

I caratteri del semaforo devono essere visualizzati come un quadrato 3x3, con una Oal centro e le posizioni della bandiera rappresentate dai personaggi | - / \. Ogni carattere semaforo deve essere separato dai caratteri adiacenti da uno spazio e ogni riga deve essere separata da una riga vuota. Non preoccuparti di racchiudere parole che potrebbero essere troppo lunghe per il tuo display - fai finta che le tue linee abbiano una lunghezza infinita.

Input di esempio:

abcdefg hijklmn opqrstu vwxyz

Uscita campione:

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

Input di esempio:

This is Code Golf.

Uscita campione:

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

\      
 O  -O 
/     \

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

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

Dato che si tratta di , vince la soluzione più breve.


1
kolmogorov-complessità ? Mi sembra che fondamentalmente si tratti di comprimere una tabella di ricerca.
Peter Taylor,

@Peter Taylor Sì, probabilmente è una buona idea aggiungere quel tag. Grazie.
migimaru,

and each row must be separated by a blank line=> ogni parola è intesa, no?
utente sconosciuto

1
Prima di leggere questo puzzle, ho erroneamente pensato che avesse a che fare con i semafori nel senso della programmazione. ¡Jajajajajja!
Thomas Eding,

@utente sconosciuto Stavo usando la riga lì per fare riferimento a una fila di caratteri semaforo . Forse usare la parola invece sarebbe stata una scelta migliore.
migimaru,

Risposte:


5

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

$_=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 alcune interruzioni di riga interessanti:

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

Mi ci è voluto un po 'per farlo funzionare (il mio primo tentativo di risposta Perl). Si basa su un'idea simile a molte altre risposte. Ogni bandiera può essere in una delle 8 posizioni, ci sono due bandiere e le due bandiere non possono mai essere nella stessa posizione. Questo significa che posso codificare la posizione di entrambi i flag in un byte, il che significa anche che posso tradurre direttamente da un carattere alla sua codifica usando la y///funzione di Perl (operatore?). Così:-

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

Perciò:

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

Sono scappato da alcuni dei personaggi che sono al di fuori del normale intervallo utilizzato per semplificare la copia e l'incollaggio del programma, ma sono abbastanza sicuro di poter scrivere un programma per sostituire i codici di escape con i caratteri stessi salvandomi circa 30 caratteri.


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)

Questo usa un mio trucco preferito: la codifica single track. Ho etichettato i bit dei semafori (sbits)

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

per ottenere il seguente diagramma di cui si verificano sbits per quale lettera:

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

ogni lettera appare esattamente due volte nel diagramma, poiché il segnalatore ha due braccia. Quindi, vedo questo come un grafico sulle lettere az, con i bordi tra le lettere che condividono sbits, con i bordi etichettati secondo lo sbit condiviso. Idealmente, troverei un percorso Hamilton attraverso questo grafico, in modo tale che i bordi successivi non abbiano la stessa etichetta. Non esistono tali percorsi ... quindi noterai che la variabile econtiene la lettera bdue volte.

Con il mio percorso quasi-Hamilton e, costruisco una serie ddi etichette sbit utilizzate nella traversata di e. Quindi, per capire dove mettere le braccia, il segnalatore deve solo trovare la lettera desiderata nella seguente tabella a portata di mano

abhioptuwycdjmnsqxzfgvklebr
6736031025071568328578162735

da dove le sue braccia vanno nella posizione direttamente sotto, e sotto e a destra della lettera.


Non sono riuscito a far funzionare questo su ideone fino a quando non sono passato to_lower()a lower(). Inoltre, ha dato un errore quando ho provato a dargli un input non alfabetico.
migimaru,

4

Scala, 272 caratteri

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

Non golf (beh, meno golf):

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

Rubino, 287 caratteri

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

L'ingresso deve essere dato su STDIN.


1

Scala 494 senza newline 520 con newline:

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

Spiegazione:

Ho osservato un modello di orologio, ma non con 12 ore, ma 8. E Starttime è 0, dove sono le 6, e a, b, c sono i primi codici, con la prima (una) bandiera a sud.

Poiché i flag 1 e 2 sono indistinguibili, possiamo prima ordinare tutte le combinazioni con il numero più basso per il primo flag. Sfortunatamente, l'ordine eccellente dall'inizio è disturbato, quando j non segue i, ma k, l, m, e in seguito diventa un casino.

Pertanto riorganizzo le mie chiavi per la mappatura:

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 sottraiamo "a" da ogni personaggio, otteniamo i numeri da (0 a 7 + 6 + 5 + ... + 1). Possiamo mappare i numeri di una griglia di caratteri

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

Una coppia di due numeri può mappare due flag, in cui il primo numero è l'indice da 0 a 6 per il primo flag e il secondo flag non è un numero compreso tra 1 e 7 per il secondo flag, ma per la distanza dal prima alla seconda bandiera. (2,2) significherebbe, la prima bandiera è a OVEST, e la seconda è a due passi in senso orario da lì, a NORD.

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

Non so molto di Scala. C'è un modo per testarlo su ideone? Ho provato a avvolgerlo in un object Main extends Applicationblocco, ma non sembra essere abbastanza.
migimaru,

IDEONE ha bisogno di una classe chiamata Main, se ricordo bene, un metodo principale, potrebbe forse estendere l'App (per scala-2.9, invece dell'applicazione (-2.8)) - e legge da stdin? In simplyscala puoi testare il codice più semplicemente. Se si sostituisce readLinenell'ultima riga con "readLine"esso dovrebbe funzionare (il codice è compatibile 2.8).
utente sconosciuto

Grazie! Non sapevo di Simplyscala, questo rende le cose molto più facili.
migimaru,

Se hai bisogno di nuovo del link: ho già inserito il link da qualche parte nel meta, dove vengono raccolte tali cose.
utente sconosciuto

Questo gestisce maiuscole?
Thomas Eding,

1

Haskell 331 357 339 caratteri

golfed:

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]

La codifica è [hour, minute]dove gli orologi hanno 8 ore e 8 minuti. I minuti si spostano più velocemente delle ore. Se un orologio segna dove l'ora e i minuti sarebbero uguali, aggiungi 1 anche all'ora e 2 al minuto (vedi l'esempio della seconda spunta sopra). Questo è l'unico modo in cui le ore aumentano. Le ore NON aumentano quando il minuto raggiunge qualche minuto arbitrario. Solo quando i minuti equivalgono a ore. Nel codice non convertito, clocktrasforma le lettere in orologi che rappresentano il semaforo. La maggior parte degli orologi sono basati sul ticchettio di quelli precedenti. Il resto è hard coded. Non c'è davvero altro nel codice.


1

Perl, 356 , 275 caratteri

Un gran numero di caratteri è stato salvato sostituendo "if else" in "? :' costruzione.

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

Il tuo codice sembra funzionare solo con lettere minuscole. Se usi al <>posto $ARGV[0]tuo puoi prendere input da stdin e usare lcper convertire tutti i caratteri in minuscolo. Questo ha l'ulteriore vantaggio di salvarti 4 caratteri. Non gestisce nemmeno caratteri non alfabetici, ma probabilmente You only need to deal with the alphabet (A-Z) and should ignore all other non-space charactersnon è molto chiaro su cosa fare con loro ...
Gareth

Non sono in grado di testare il codice in questo momento, ma sembra che il codice stampi solo spazi per caratteri non alfa, il che va bene.
migimaru,

@migimaru Proverò a correggerlo.
zura,

@zura È accettabile la stampa di spazi per caratteri non alfabetici. Non è necessario risolverlo.
migimaru,

0

PowerShell , 198 192 191 188 byte

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

Provalo online!

L'output contiene una riga vuota della coda.

Meno golf:

-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

Carbone , 70 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

F⪪↧S «

Dividi l'input in lettere minuscole negli spazi e passa sopra ogni parola.

Fι«

Passa sopra ogni personaggio.

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

Dividi la stringa compressa fjmrwyz gnsvxz abcdefg ahiklmn bhopqrs ciotuy djkptv elquwxnegli spazi e passa sopra ogni gruppo di lettere.

P⊗№λκ

Se il gruppo contiene la lettera corrente, traccia una linea nella direzione corrente.

↷¹»

Ruota di 45 ° in senso orario.

oM³→»

Invia il centro oe passa alla posizione della lettera successiva.

⸿M³↓

Passa all'inizio della parola successiva.

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.