优化ASCII试管


13

您会得到一堆ASCII试管,您的任务是减少所用试管的数量。

每个试管如下所示:

|  |
|  |
|  |
|~~|
|  |
|  |
|  |
|  |
|__|

显然~~是水位。试管也可以是空的,在这种情况下,里面没有~~字符。单管最多可容纳8个水位单元。

您将获得有限数量的内部不同水位的试管。您必须将水尽可能少地倒入试管中,然后输出结果。

|  | |  | |  | |  |         |~~| |  |
|  | |  | |  | |  |         |  | |  |
|  | |~~| |  | |  |         |  | |  |
|~~| |  | |  | |  |         |  | |~~|
|  | |  | |  | |  | ------> |  | |  |
|  | |  | |  | |  |         |  | |  |
|  | |  | |~~| |  |         |  | |  |
|  | |  | |  | |  |         |  | |  |
|__| |__| |__| |__|         |__| |__|

 05 + 06 + 02 + 00  ------>  08 + 05

如您所见,试管用单个空格隔开。空管不应在输出中显示。这是代码高尔夫,因此字节数最少的代码获胜。

测试案例:http : //pastebin.com/BC0C0uii

打高尔夫球快乐!


我们也可以重新分配水吗?例如,对于您的示例,7 + 6是有效的输出吗?
马丁·恩德

@MartinEnder您应该使用最少数量的试管。我认为在这种情况下可以接受。
Jacajack

@StewieGriffin我还没有在这里看到任何类似的东西,所以如果有点重复,我很抱歉
Jacajack

是否允许尾随空格?
PurkkaKoodari

更好的标题-“ Optimizer ASCII试管婴儿”
Optimizer

Answers:



4

的JavaScript(ES6),159个 148字节的

s=>s.replace(/~~|\n/g,c=>1/c?i++:n+=7-i,n=i=-1)&&`012345678`.replace(/./g,i=>`|${g(+i)}| `.repeat(n>>3)+`|${g(~n&7^i)}|
`,g=i=>i?i>7?`__`:`  `:`~~`)

输出尾随换行符。编辑:在@Arnauld的帮助下保存了11个字节。


s.replace(/~~/g,(_,i)=>n+=9-i/s.indexOf`\n`|0,n=0)应该保存4个字节。您可能想将n初始化为-1,然后使用n>>3~n&7^i保存一个字节。
Arnauld

@Arnauld感谢您的-1想法,但是我能够改进这个replace想法。
尼尔

1
真好!我从未意识到这1/"\n"是真的。
Arnauld

@Arnauld好吧,这只是锦上添花……
Neil

3

Perl,150个字节

149个字节的代码+ -n标志。

$l+=9-$.for/~~/g}if($l){$%=($v=$l/8)+($r=$l!=8);say"|~~| "x$v.($@="|  | ")x$r;say$:=$@x$%for$l%8..6;say$@x$v."|~~|"x$r;say$:for 2..$l%8;say"|__| "x$%

我不会解释所有代码,仅介绍几件事:
$l+=9-$.for/~~/g计算输入中的水量。
代码的第二部分显示输出。这个想法是要放置尽可能多的充满水的试管,最后一个试管中要放剩下的水(如果有的话)。所以该算法是在4个部分:打印的水的第一行(管的顶部): say"|~~| "x$v.($@="| | ")x$r。然后,打印空的试管部分,直到达到最后一个试管的水位:say$:=$@x$%for$l%8..6。然后打印最后一根管子的水位:say$@x$v."|~~|"x$r。然后,打印所有剩余的“空”级别:say$:for 2..$l%8;。最后,打印底线:say"|__| "x$%
变量名使它难以阅读($%$@$:)但允许类似的关键字xfor 要写在变量后无空格。

要运行它:

perl -nE '$l+=9-$.for/~~/g}if($l){$%=($v=$l/8)+($r=$l!=8);say"|~~| "x$v.($@="|  | ")x$r;say$:=$@x$%for$l%8..6;say$@x$v."|~~|"x$r;say$:for 2..$l%8;say"|__| "x$%' <<< "|  | |  | |  | |  |
|  | |  | |  | |  |
|  | |~~| |  | |  |
|~~| |  | |  | |  |
|  | |  | |  | |  |
|  | |  | |  | |  |
|  | |  | |~~| |  |
|  | |  | |  | |  |
|__| |__| |__| |__| "

我对这个答案有多长时间并不满意。我尝试尽最大努力利用算法,但是使用其他方法可能会更短。我会尽快尝试。


@JamesHolderness我尝试了所有测试用例(现在重新尝试,因为您怀疑我),对我来说似乎很好。“最后一个”是带有3个管的那个:2个管的水位为4,1个管的水位为2,对吗?如果是这样,那么我尝试了一下,它的输出与Pastbin上的输出相同
Dada

@JamesHolderness哦,对,它解释了很多东西!谢谢:)
达达

3

Befunge,144个 138字节

9>1-00p>~$~2/2%00gv
 |:g00_^#%4~$~$~+*<
$< v01!-g01+*8!!\*!\g00::-1</8+7:<p01-1<9p00+1%8-1:_@#:
_ ~>g!-1+3g:"|",,," |",,:>#^_$55+,10g:#^_@

在线尝试!

前两行处理输入,基本上忽略所有内容,除了每个试管中的第一个字符(可能是水平标记)。我们用那个字符的ASCII值除以2和mod 2(根据我们是否在水平标记上来给我们1或0),再乘以行号(从8开始倒数,从而得出该管的液位值),并将其添加到运行总计中。

输出在第二两行中处理,基本上从第三行的最右边开始。我们首先通过将总水位加7除以8来计算试管的数量,然后在所有试管的行上进行迭代时,我们计算要显示在特定试管内的字符(t,倒数为0)。给定的行(r从8倒数到0)如下:

last_level = (total_water - 1)%8 + 1
level      = last_level*!t + 8*!!t
char_type  = !(level - r) - !r

对于最底行(管的底部),计算得出的char_type为-1,对于非水位的任何其他区域,计算的char_type为0,对于水位,则为1。因此,它可以用作简单的表查找以输出适当的字符(您可以在第4行的开头看到此表)。


2

Haskell,186个字节

import Data.Lists
z=[8,7..0]
f x|s<-sum[i*length j-i|(i,j)<-zip z$splitOn"~~"<$>lines x],s>0=unlines$(\i->(#i)=<<(min 8<$>[s,s-8..1]))<$>z|1<2=""
l#i|i==l="|~~| "|i<1="|__| "|1<2="|  | "

用法示例:

*Main> putStr $ f "|  | |  | |  | |  |\n|  | |  | |  | |  |\n|  | |~~| |  | |  |\n|~~| |  | |  | |  |\n|  | |  | |  | |  |\n|  | |  | |  | |  |\n|  | |  | |~~| |  |\n|  | |  | |  | |  |\n|__| |__| |__| |__|"
|~~| |  | 
|  | |  | 
|  | |  | 
|  | |~~| 
|  | |  | 
|  | |  | 
|  | |  | 
|  | |  | 
|__| |__| 

在每行上放置尾随空格。怎么运行的:

              lines x      -- split the input string at newlines             
      splitOn"~~"<$>       -- split every line on "~~"
    zip z                  -- pair every line with its water level, i.e.
                           -- first line = 8, 2nd = 7 etc.
   [i*length j-i|(i,j)   ] -- for each such pair take the number of "~~" found
                           -- times the level
 s<-sum                    -- and let s be the sum, i.e. the total amount of water

  s>0                      -- if there's any water at all

          [s,s-8..1]       -- make a list water levels starting with s
                           -- down to 1 in steps of 8
       min 8<$>            -- and set each level to 8 if its greater than 8
                           -- now we have the list of water levels for the output
  \i->(#i)=<<(  )<$>z      -- for each number i from 8,7..0 map (#i) to the
                           -- list of output water levels and join the results
unlines                    -- join output lines into a single string (with newlines)

l#i                        -- pick a piece of tube:
                           --  |__|  if l==0
                           --  |~~|  if l==i
                           --  |  |  else



  |1<2=""                  -- if there's no water in the input, return the
                           -- empty string

主要的麻烦是缺少一个计算字符串中子字符串出现频率的函数。还有countData.Text,但在导入它导致了一堆名字冲突,这都太昂贵的决心。


1

Python,261个字节

i=input().split('\n')
t=0
R=range(9)[::-1]
for n in R:t+=i[n].count('~')/2*(8-n)
m=t%8
e=t/8
o=t/8+1
T='|~~| '
b='|  | '
B='|__| '
n='\n'
if m:
 print T*e+b
 for n in R:
    if n==m:print b*e+T
    else:print b*o
 print B*o
elif t<1:1
else:print T*e+(n+b*e)*7+(n+B)*e

我觉得我缺少一些东西。另外,如果一堆换行符可用于空白输出,那么我可能会丢失一些字节。接受类似的输入'| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n|__| |__| |__|'


1

红宝石,139字节

(138个字节的代码,再加上一个字节-n

n||=0;b=gsub(/~~/){n=n+9-$.}[0,5];END{8.times{|i|puts (b*(n/8)).tr(?_,i>0??\ :?~)+(n%8>0?b.tr(?_,(8-i==n%8)??~:?\ ):"")};puts b*((n+7)/8)}

在线尝试!

一些解释:

该程序需要-n开关。

n –水计数器。

b–建造管的模板;等于"|__| "

i –管道制造过程中的电流线索引。

gsub(/~~/){}–这种滥用gsub只是简单地计算水位。gsub实际上扩展到Kernel.gsub,等于$_.gsub!。这不必要地操纵了当前行($_);但是,它允许对b=... [0,5]而不是进行更简洁的分配b=$_[0,5]

n=n+9-$.–要测量水位,该表达式使用预定义变量$.,该变量包含当前输入行号。这使我失去了显式循环变量。

b=gsub(/~~/){}[0,5]–将最左侧试管的底部缓存为模板。(因为赢
了底线,所以感觉有点像“开罗大象”的图案。)由于试管的底部从不显示水,因此gsub当我们到达那里时,水不会替代任何东西。因此,最后b总是等于"|__| "

END{}–在处理完整个输入流后调用。我用这个阶段来构造目标管。

i>0??\ :?~–是的简写i > 0 ? " " : "~"

更新1:添加了有关变量,gsub欺骗和END{}阶段的详细信息。

更新2 :( 整体±0字节)

  • 使用n||=0代替n=n||0 (-1字节)
  • 恶意-n (+1字节)

0

Python 3,404字节

该程序以ASCII和数字格式创建带有水位的完整预期输出。

w,x,y=[],[],[];a,b,s=" ------> ","~","";y=input().split("\n")
for i in [i for i in zip(*y) if "_" in i][::2]:w+=[8-i.index(b)] if b in i else [0]
u=sum(w)
while u:x+=[[8],[u]][u<8];u-=x[-1]
for i,k in enumerate(y):
    s+=k+"%s"%[a," "*9][i!=4]
    for j,l in enumerate(x):
        c=["  ","__"][i==8];s+="|%s| "%(c,b*2)[l==8-i]
    s+="\n"
s+="\n"
for i in w:s+=" %02d  "%i
s+="\b"+a
for i in x:s+=" %02d  "%i
print(s)
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.