Flag Semaphore Encoder

12

Votre objectif est d'écrire un encodeur de sémaphore de drapeau , qui convertira une phrase donnée en caractères de sémaphore de drapeau correspondants, selon le système de sémaphore décrit sur Wikipedia .

Supposons que l'entrée est une seule phrase fournie via stdin (ou équivalent). Votre sortie doit être une série de caractères sémaphores, chaque ligne représentant un mot de la phrase. Vous devez uniquement gérer l'alphabet (AZ) et devez ignorer tous les autres caractères non-espace, mais vous devez être capable de gérer à la fois les majuscules et les minuscules. Votre sortie est autorisée à contenir des espaces supplémentaires.

Les caractères du sémaphore doivent être affichés sous la forme d'un carré 3x3, avec un Oau milieu et les positions du drapeau représentées par les caractères | - / \. Chaque caractère sémaphore doit être séparé des caractères adjacents par un espace et chaque ligne doit être séparée par une ligne vierge. Ne vous inquiétez pas de l'habillage des mots qui peuvent être trop longs pour votre affichage - faites comme si vos lignes avaient une longueur infinie.

Exemple d'entrée:

abcdefg hijklmn opqrstu vwxyz

Exemple de sortie:

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

Exemple d'entrée:

This is Code Golf.

Exemple de sortie:

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

\      
 O  -O 
/     \

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

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

Puisqu'il s'agit de , la solution la plus courte l'emporte.

migimaru
la source
1
kolmogorov-complexité ? Il me semble qu'il s'agit fondamentalement de compresser une table de recherche.
Peter Taylor
@Peter Taylor Oui, c'est probablement une bonne idée d'ajouter cette balise. Merci.
migimaru
and each row must be separated by a blank line=> chaque mot est destiné, n'est-ce pas?
utilisateur inconnu
1
Avant de lire ce puzzle, je pensais à tort qu'il s'agissait de sémaphores au sens de la programmation. ¡Jajajajajja!
Thomas Eding
@user unknown J'utilisais row ici pour faire référence à une rangée de caractères sémaphores . Peut-être qu'utiliser le mot à la place aurait été un meilleur choix.
migimaru

Réponses:

5

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

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

Avec quelques jolis sauts de ligne:

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

Il m'a fallu un certain temps pour que cela fonctionne (ma première tentative de réponse Perl). Il est basé sur une idée similaire à beaucoup d'autres réponses. Chaque drapeau peut être dans l'une des 8 positions, il y a deux drapeaux et les deux drapeaux ne peuvent jamais être dans la même position. Cela signifie que je peux encoder la position des deux drapeaux dans un octet - ce qui signifie également que je peux traduire directement d'un caractère à son encodage en utilisant la y///fonction Perl (opérateur?). Donc:-

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

Donc:

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

J'ai échappé à un bon nombre de caractères qui se trouvent en dehors de la plage normale utilisée pour faciliter la copie et le collage du programme - mais je suis presque sûr que je pourrais écrire un programme pour remplacer les codes d'échappement par les caractères eux-mêmes me sauvant environ 30 caractères.

Gareth
la source
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)

Cela utilise une de mes astuces préférées: l'encodage à piste unique. J'ai étiqueté les bits de sémaphore (sbits)

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

pour obtenir le graphique suivant dont les sbits se produisent pour quelle lettre:

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

chaque lettre apparaît exactement deux fois dans la carte, car le signaleur a deux bras. Ensuite, je vois cela comme un graphique sur les lettres az, avec des bords entre les lettres partageant des sbits, avec les bords étiquetés en fonction du sbit partagé. Idéalement, je trouverais un chemin Hamilton à travers ce graphique, de sorte que les bords suivants n'ont pas la même étiquette. Aucun chemin de ce type n'existe ... vous remarquerez donc que la variable econtient bdeux fois la lettre .

Avec mon chemin presque Hamilton e, je construis un tableau dd'étiquettes sbit utilisées dans la traversée de e. Ensuite, pour savoir où mettre ses bras, le signaleur n'a qu'à trouver la lettre souhaitée dans le tableau pratique suivant

abhioptuwycdjmnsqxzfgvklebr
6736031025071568328578162735

d'où ses bras vont dans la position directement en dessous, en dessous et à droite de la lettre.

boothby
la source
Je ne pouvais pas faire fonctionner ça sur ideone jusqu'à ce que je change to_lower()pour lower(). En outre, il a donné une erreur lorsque j'ai essayé de lui donner une entrée non alphabétique.
migimaru
4

Scala, 272 caractères

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é (enfin, moins 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")
)
Rex Kerr
la source
2

Rubis, 287 caractères

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'entrée doit être donnée sur STDIN.

Howard
la source
1

Scala 494 sans retour à la ligne 520 avec retour à la ligne:

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

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

Explication:

J'ai observé un modèle d'horloge, mais pas avec 12 heures, mais 8. Et Starttime est 0 est, où 6 heures est, et a, b, c sont les premiers codes, avec le premier (un) drapeau sur le Sud.

Étant donné que les drapeaux 1 et 2 sont indiscernables, nous pouvons d'abord trier toutes les combinaisons avec le numéro le plus bas pour le premier drapeau. Malheureusement, l'ordre fin du début est perturbé, lorsque j ne suit pas i, mais k, l, m, et plus tard, c'est un gâchis.

Par conséquent, je réorganise mes clés pour le mappage:

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 nous soustrayons 'a' de chaque caractère, nous obtenons les nombres de (0 à 7 + 6 + 5 + ... + 1). Nous pouvons cartographier les nombres d'une grille de caractères

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

Une paire de deux nombres peut mapper deux drapeaux, où le premier nombre est l'index de 0 à 6 pour le premier drapeau, et le deuxième drapeau n'est pas un nombre de 1 à 7 pour le deuxième drapeau, mais pour la distance du premier au deuxième drapeau. (2,2) signifierait que le premier drapeau est à l'OUEST et le second est à deux pas dans le sens des aiguilles d'une montre de là, vers le 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))
Utilisateur inconnu
la source
Je ne connais pas grand-chose à Scala. Existe-t-il un moyen de tester cela sur ideone? J'ai essayé de l'envelopper dans un object Main extends Applicationbloc, mais cela ne semble pas être suffisant.
migimaru
IDEONE a besoin d'une classe nommée Main, si je me souviens bien, une méthode principale, devrait peut-être étendre App (pour scala-2.9, au lieu d'Application (-2.8)) - et lit-elle depuis stdin? Dans simplyscala, vous pouvez tester le code plus simplement. Si vous remplacez readLinedans la dernière ligne avec "readLine"cela devrait fonctionner (le code est compatible 2.8).
utilisateur inconnu
Merci! Je ne connaissais pas simplyscala, cela rend les choses beaucoup plus faciles.
migimaru
Si vous avez à nouveau besoin du lien: j'ai déjà inséré le lien quelque part dans la méta, où de telles choses sont collectées.
utilisateur inconnu
Est-ce que cela gère les majuscules?
Thomas Eding le
1

Haskell 331 357 339 caractères

Golfé:

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

Non 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]

L'encodage est l' [hour, minute]endroit où les horloges ont 8 heures et 8 minutes. Les minutes avancent plus vite que les heures. Si une horloge coche où l'heure et la minute seraient égales, ajoutez également 1 à l'heure et 2 à la minute (voir le deuxième exemple de coche ci-dessus). C'est la seule façon d'augmenter les heures. Les heures n'augmentent PAS lorsque la minute atteint une minute arbitraire. Seulement quand les minutes seraient égales aux heures. Dans le code non golfé, clocktransforme les lettres en horloges qui représentent le sémaphore. La plupart des horloges sont construites sur la base du tic-tac des précédentes. Les autres sont codés en dur. Il n'y a rien de plus dans le code.

Thomas Eding
la source
1

Perl, 356 , 275 caractères

Un grand nombre de caractères a été enregistré en remplaçant «sinon» par «? :' construction.

@_=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
la source
Votre code ne semble fonctionner que pour les lettres minuscules. Si vous utilisez à la <>place de $ARGV[0]vous pouvez prendre l'entrée de stdin et utiliser lcpour convertir tous les caractères en minuscules. Cela a l'avantage supplémentaire de vous faire économiser 4 caractères. Il ne gère pas non plus les caractères non alphabétiques, mais sans doute You only need to deal with the alphabet (A-Z) and should ignore all other non-space characterspas très clair sur ce qu'il faut en faire ...
Gareth
Je ne suis pas en mesure de tester le code pour le moment, mais il semble que le code imprime simplement des espaces pour les caractères non alpha, ce qui est bien.
migimaru
@migimaru Je vais essayer de le corriger.
zura
@zura L'impression d'espaces pour les caractères non alphabétiques est acceptable. Vous n'avez pas besoin de réparer ça.
migimaru
0

PowerShell , 198 192 191 188 octets

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

Essayez-le en ligne!

La sortie contient une ligne vide de queue.

Moins 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' '
    }
    ''
}
mazzy
la source
0

Fusain , 70 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

F⪪↧S «

Divisez l'entrée en minuscules sur les espaces et bouclez sur chaque mot.

Fι«

Faites une boucle sur chaque personnage.

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

Divisez la chaîne compressée fjmrwyz gnsvxz abcdefg ahiklmn bhopqrs ciotuy djkptv elquwxsur les espaces et bouclez sur chaque groupe de lettres.

P⊗№λκ

Si le groupe contient la lettre actuelle, tracez une ligne dans la direction actuelle.

↷¹»

Tournez de 45 ° dans le sens des aiguilles d'une montre.

oM³→»

Sortez le centre oet passez à la position de la lettre suivante.

⸿M³↓

Passez au début du mot suivant.

Neil
la source