标记信号量编码器


12

您的目标是编写一个标志信号量编码器,根据Wikipedia上描述的信号量系统,它将给定的句子转换为相应的标志信号量字符。

假设输入是通过stdin(或等效输入)提供的单个句子。您的输出应该是一系列的信号量字符,每一行代表该句子中的一个单词。您只需要处理字母(AZ),并且应该忽略所有其他非空格字符,但是您必须能够处理大写和小写字母。您的输出允许包含额外的空格。

信号量字符必须显示为3x3的正方形,O中间是,标记位置由字符表示| - / \。每个信号量字符必须与相邻字符之间用空格分隔,并且每一行必须由空白行分隔。不必担心包装可能对于您的显示而言太长的单词-假装您的行有无限长。

输入样例:

abcdefg hijklmn opqrstu vwxyz

样本输出:

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

输入样例:

This is Code Golf.

样本输出:

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

\      
 O  -O 
/     \

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

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

由于这是,因此最短的解决方案将获胜。


1
kolmogorov-复杂性?在我看来,从根本上来说,这是关于压缩查找表。
彼得·泰勒

@Peter Taylor是的,添加该标签可能是一个好主意。谢谢。
migimaru 2011年

and each row must be separated by a blank line=>每个单词的意思是不是?
用户未知

1
在阅读此难题之前,我错误地认为它与编程意义上的信号量有关。¡Jajajajajja!
Thomas Eding

@user unknown我在那儿使用行来引用一行信号量字符。也许改为使用单词将是更好的选择。
migimaru 2011年

Answers:


5

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

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

有一些漂亮的换行符:

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

我花了一些时间才能完成此工作(我第一次尝试Perl回答)。它基于与许多其他答案相似的思想。每个标志可以位于8个位置之一,有两个标志,并且两个标志永远不能位于同一位置。这意味着我可以将两个标志的位置编码在一个字节中-这也意味着我可以使用Perl的y///函数(运算符?)将字符直接转换成其编码。所以:-

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

因此:

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

为了使程序的复制和粘贴变得容易,我已经逃避了一些超出正常使用范围的字符,但是我很确定我可以编写一个程序来用字符本身替换转义代码,从而节省了我的时间大约30个字符。


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)

这使用了我最喜欢的一个技巧:单轨编码。我已经标记了信号量位(sbits)

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

获得以下图表,其中哪个字母出现在哪个字母上:

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

由于信号员有两条手臂,因此每个字母在图表中恰好出现两次。然后,我将其视为字母az上的图形,字母之间的边共享位,并根据共享位标记边。理想情况下,我将在该图中找到一条汉密尔顿路径,以使随后的边没有相同的标签。不存在这样的路径...因此您会注意到该变量两次e包含字母b

通过接近汉密尔顿的路径e,我构造了d用于遍历的位标签数组e。然后,要弄清楚将手臂放在哪里,信号员只需在以下方便的图表中找到所需的字母

abhioptuwycdjmnsqxzfgvklebr
6736031025071568328578162735

她的手臂因此而处于字母正下方,正下方和右下方的位置。


在更改to_lower()为之前,我无法在ideone上运行它lower()。另外,当我尝试提供非字母输入时,它给出了一个错误。
migimaru 2011年

4

Scala,272个字符

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

空球(好球,少球):

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个字符

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

输入必须在STD​​IN上给出。


1

不带换行符的 Scala 494换行符 520:

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

松开

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

说明:

我观察到了一种时钟模式,但不是12小时,而是8小时。Starttime是0,这里是6点钟,并且a,b,c是第一个代码,在南有第一个(一个)标志。

由于标记1和2是无法区分的,因此我们可以首先对第一个标记使用较低编号对所有组合进行排序。不幸的是,当j不跟随i,但是k,l,m后来又变得一团糟时,从一开始的良好顺序就被打乱了。

因此,我重新安排了映射的键:

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

如果我们从每个字符中减去“ a”,我们得到的数字为(0到7 + 6 + 5 + ... + 1)。我们可以映射一个字符网格的数字

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

一对两个数字可以映射两个标志,其中第一个数字是第一个标志的0到6的索引,第二个标志不是第二个标志从1到7的数字,而是与第一到第二个标志。(2,2)表示,第一个标记位于WEST,第二个标记则是从那里顺时针方向到北的两步。

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

我对Scala不太了解。有什么方法可以在ideone上测试吗?我尝试将其包装在一个object Main extends Application块中,但这似乎还不够。
migimaru 2011年

IDEONE需要一个名为Main的类,如果我没有记错的话,它应该是一个main方法,应该扩展App(用于scala-2.9,而不是Application(-2.8)),并且它是否从stdin中读取?在simplescala中,您可以更简单地测试代码。如果readLine在最后一行替换"readLine"它,它应该可以工作(该代码与2.8兼容)。
用户未知,

谢谢!我不了解simplescala,这使事情变得容易得多。
migimaru's

如果您再次需要该链接:我已经将链接插入了meta中的某处,收集了这些东西。
用户未知,

这会处理大写吗?
Thomas Eding

1

哈斯克尔331 357 339字符

打高尔夫球:

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

取消高尔夫:

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]

[hour, minute]时钟是8小时8分钟的地方是编码。分钟的移动速度快于小时。如果时钟在小时和分钟等于的位置滴答滴答,则在小时和分钟上分别加上1和2(请参见上面的第二个滴答示例)。这是增加小时数的唯一方法。当分钟达到任意分钟数时,小时数不会增加。只有分钟等于几小时。在非高尔夫代码中,clock将字母变成代表信号量的时钟。大多数时钟都是基于先前时钟的滴答而建立的。其余的都是硬编码的。真正没有更多的代码。


1

Perl,356个,275个字符

通过将'if else'替换为'?,可以节省大量字符。:'施工。

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

您的代码似乎仅适用于小写字母。如果您使用<>而不是,则$ARGV[0]可以从stdin接受输入,并使用lc将所有字符转换为小写。这具有为您节省4个字符的额外好处。它也不能处理非字母字符,但是可以说You only need to deal with the alphabet (A-Z) and should ignore all other non-space characters对它们的处理方式还不是很清楚……
Gareth

我现在无法测试代码,但是看起来代码只是为非字母字符打印空格,这很好。
migimaru 2011年

@migimaru我会尝试纠正它。
zura 2011年

@zura可以打印非字母字符的空格。您无需修复该问题。
migimaru 2011年

0

PowerShell中198个 192 191 188字节

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

在线尝试!

输出包含一个尾部空行。

少打高尔夫球:

-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

木炭,70字节

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

在线尝试!链接是详细版本的代码。说明:

F⪪↧S «

在空格处分割小写输入,并在每个单词上循环。

Fι«

循环播放每个字符。

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

fjmrwyz gnsvxz abcdefg ahiklmn bhopqrs ciotuy djkptv elquwx在空格处分割压缩的字符串,然后遍历每个字母组。

P⊗№λκ

如果组中包含当前字母,则沿当前方向画一条线。

↷¹»

顺时针旋转45°。

oM³→»

输出中心o并移至下一个字母的位置。

⸿M³↓

移至下一个单词的开头。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.