Oznacz koder semaforów

12

Twoim celem jest napisanie kodera semaforów flag , który przekształci dane zdanie w odpowiednie znaki semaforów flag, zgodnie z systemem semaforów opisanym na Wikipedii .

Załóżmy, że dane wejściowe są pojedynczym zdaniem podanym przez stdin (lub odpowiednik). Twój wynik powinien składać się z szeregu znaków semaforów, przy czym każdy wiersz reprezentuje jedno słowo z zdania. Musisz tylko radzić sobie z alfabetem (AZ) i powinieneś ignorować wszystkie inne znaki spacji, ale musisz umieć obsługiwać zarówno wielkie, jak i małe litery. Twoje dane wyjściowe mogą zawierać dodatkowe białe znaki.

Znaki semafora muszą być wyświetlane jako kwadrat 3 x 3, z Opośrodkiem i pozycjami flagi reprezentowanymi przez znaki | - / \. Każdy znak semafora musi być oddzielony od sąsiednich znaków spacją, a każdy wiersz musi być oddzielony pustą linią. Nie przejmuj się zawijaniem słów, które mogą być zbyt długie dla twojego wyświetlacza - udawaj, że twoje linie mają nieskończoną długość.

Przykładowe dane wejściowe:

abcdefg hijklmn opqrstu vwxyz

Przykładowe dane wyjściowe:

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

Przykładowe dane wejściowe:

This is Code Golf.

Przykładowe dane wyjściowe:

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

\      
 O  -O 
/     \

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

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

Ponieważ jest to , wygrywa najkrótsze rozwiązanie.

migimaru
źródło
1
złożoność Kołmogorowa ? Wydaje mi się, że zasadniczo chodzi o kompresowanie tabeli odnośników.
Peter Taylor,
@Peter Taylor Tak, prawdopodobnie dobrym pomysłem jest dodanie tego tagu. Dzięki.
migimaru,
and each row must be separated by a blank line=> każde słowo ma na myśli, prawda?
użytkownik nieznany
1
Zanim przeczytałem tę łamigłówkę, błędnie pomyślałem, że ma ona związek z semaforami w sensie programowania. ¡Jajajajajja!
Thomas Eding,
@ użytkownik nieznany Użyłem tam wiersza, aby odnieść się do wiersza znaków semafora . Być może użycie słowa byłoby lepszym wyborem.
migimaru,

Odpowiedzi:

5

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

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

Z pewnymi upiększającymi podziałami linii:

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

Zajęło mi trochę czasu, aby to zadziałało (moja pierwsza próba odpowiedzi na Perla). Opiera się na podobnym pomyśle do wielu innych odpowiedzi. Każda flaga może znajdować się w jednej z 8 pozycji, są dwie flagi, a dwie flagi nigdy nie mogą być w tej samej pozycji. Oznacza to, że mogę zakodować pozycję obu flag w jednym bajcie - co oznacza również, że mogę tłumaczyć bezpośrednio ze znaku na jego kodowanie za pomocą y///funkcji Perla (operator?). Więc:-

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

W związku z tym:

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

Uciekłem sporej liczbie znaków spoza normalnie używanego zakresu, aby ułatwić kopiowanie i wklejanie programu - ale jestem całkiem pewien, że mógłbym napisać program, który zastąpiłby kody ucieczki samymi zapisującymi mnie znakami około 30 znaków.

Gareth
źródło
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)

Wykorzystuje to moją ulubioną sztuczkę: kodowanie jednościeżkowe. Oznaczyłem bity semafora (sbits)

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

aby uzyskać następującą tabelę, które sekwencje występują dla której litery:

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

każda litera występuje dokładnie dwa razy na mapie, ponieważ sygnalizator ma dwa ramiona. Następnie widzę to jako wykres na literach az, z krawędziami między literami dzielącymi fragmenty, z krawędziami oznaczonymi zgodnie ze wspólnym bitem. Idealnie byłoby znaleźć ścieżkę Hamiltona przez ten wykres, tak aby kolejne krawędzie nie miały tej samej etykiety. Nie ma takich ścieżek ... więc zauważysz, że zmienna ezawiera literę bdwa razy.

Na mojej ścieżce prawie Hamiltona ekonstruuję tablicę detykiet sbit używanych podczas przechodzenia e. Następnie, aby dowiedzieć się, gdzie położyć ręce, sygnalizator musi znaleźć tylko pożądaną literę na poniższej poręcznej tabeli

abhioptuwycdjmnsqxzfgvklebr
6736031025071568328578162735

skąd jej ramiona idą w pozycję bezpośrednio poniżej, a także poniżej i na prawo od litery.

boothby
źródło
Nie mogłem dostać to do uruchomienia na ideone dopóki nie zmienił to_lower()się lower(). Ponadto wystąpił błąd, gdy próbowałem podać dane niealfabetyczne.
migimaru,
4

Scala, 272 znaków

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

Nie golfowy (no, mniej golfowy):

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
źródło
2

Ruby, 287 znaków

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

Dane wejściowe należy podać na STDIN.

Howard
źródło
1

Scala 494 bez nowych linii 520 z nowymi liniami:

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

bez golfa:

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

Wyjaśnienie:

Obserwowałem wzorzec zegara, ale nie z 12 godzinami, ale 8. A Starttime wynosi 0, gdzie jest godzina 6, a a, b, c są pierwszymi kodami, z pierwszą (jedną) flagą na południu.

Ponieważ flagi 1 i 2 są nierozróżnialne, możemy najpierw sortować wszystkie kombinacje z niższą liczbą dla pierwszej flagi. Niestety porządek od początku jest zakłócany, gdy j nie podąża za i, ale k, l, m, a później robi się bałagan.

Dlatego zmieniam układ klawiszy na mapowanie:

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

Jeśli odejmiemy „a” od każdego znaku, otrzymamy liczby od (0 do 7 + 6 + 5 + ... + 1). Możemy zmapować numery siatki znaków

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

Para dwóch liczb może odwzorować dwie flagi, gdzie pierwsza liczba jest indeksem od 0 do 6 dla pierwszej flagi, a druga flaga nie jest liczbą od 1 do 7 dla drugiej flagi, ale dla odległości od pierwsza do drugiej flagi. (2,2) oznaczałoby, że pierwsza flaga jest na zachód, a druga to dwa kroki stamtąd zgodnie z ruchem wskazówek zegara, do PÓŁNOCNEJ.

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))
nieznany użytkownik
źródło
Nie wiem wiele o Scali. Czy istnieje sposób, w jaki mogę to przetestować na ideone? Próbowałem zawinąć w object Main extends Applicationblok, ale to nie wydaje się wystarczające.
migimaru,
IDEONE potrzebuje klasy o nazwie Main, jeśli dobrze pamiętam, główna metoda powinna rozszerzyć App (dla scala-2.9 zamiast Application (-2.8)) - i czy odczytuje ze standardowego wejścia? W simplyscala możesz w prosty sposób przetestować kod. Jeśli zastąpisz go readLinew ostatnim wierszu "readLine", powinien on działać (kod jest zgodny z 2.8).
użytkownik nieznany
Dzięki! Nie wiedziałem o simplescala, co znacznie ułatwia.
migimaru
Jeśli potrzebujesz ponownie linku: wstawiłem już link gdzieś w meta, gdzie gromadzone są takie rzeczy.
użytkownik nieznany
Czy to obsługuje wielkie litery?
Thomas Eding,
1

Haskell 331 357 339 znaków

Gra w golfa:

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

Nie golfowany:

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]

Kodowanie polega na tym, [hour, minute]że zegary mają 8 godzin i 8 minut. Minuty poruszają się szybciej niż godziny. Jeśli zegar tyka, gdy godzina i minuta byłyby równe, dodaj 1 do godziny i 2 do minuty (patrz drugi przykład zaznaczenia powyżej). To jedyny sposób na zwiększenie godzin. Godziny NIE rosną, gdy minuta osiągnie dowolną minutę. Tylko wtedy, gdy minuty będą równe godzinom. W kodzie bez golfa clockzamienia litery w zegary reprezentujące semafor. Większość zegarów jest zbudowana na podstawie tykania z poprzednich. Reszta jest na stałe zakodowana. W kodzie nie ma nic więcej.

Thomas Eding
źródło
1

Perl, 356 , 275 znaków

Zapisano dużą liczbę znaków, zastępując „jeśli jeszcze” na „? : „konstrukcja.

@_=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
źródło
Twój kod działa tylko na małe litery. Jeśli używasz <>zamiast $ARGV[0], możesz pobrać dane wejściowe ze standardowego wejścia i użyć lcdo konwersji wszystkich znaków na małe litery. Ma to dodatkową zaletę polegającą na oszczędzeniu 4 znaków. Nie obsługuje też znaków innych niż alfabet, ale zapewne You only need to deal with the alphabet (A-Z) and should ignore all other non-space charactersnie jest jasne, co z nimi zrobić ...
Gareth
Obecnie nie jestem w stanie przetestować kodu, ale wygląda na to, że kod po prostu drukuje spacje dla znaków innych niż alfa, co jest w porządku.
migimaru
@migimaru Spróbuję to naprawić.
zura
@zura Dopuszczalne jest drukowanie spacji dla znaków innych niż alfabet. Nie musisz tego naprawiać.
migimaru,
0

PowerShell , 198 192 191 188 bajtów

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

Wypróbuj online!

Dane wyjściowe zawierają jeden pusty wiersz ogona.

Mniej golfa:

-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
źródło
0

Węgiel drzewny , 70 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

F⪪↧S «

Podziel małe litery na spacje i zapętlaj każde słowo.

Fι«

Pętla nad każdą postacią.

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

Podziel skompresowany ciąg znaków fjmrwyz gnsvxz abcdefg ahiklmn bhopqrs ciotuy djkptv elquwxna spacje i zapętlaj każdą grupę liter.

P⊗№λκ

Jeśli grupa zawiera bieżącą literę, narysuj linię w bieżącym kierunku.

↷¹»

Obróć o 45 ° w prawo.

oM³→»

Wyjmij środek oi przejdź do pozycji następnej litery.

⸿M³↓

Przejdź na początek następnego słowa.

Neil
źródło