ASCII 테스트 튜브 최적화


13

많은 ASCII 테스트 튜브가 제공되며, 사용되는 테스트 튜브 수를 줄이는 것입니다.

각 테스트 튜브는 다음과 같습니다.

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

분명히 ~~수위입니다. 시험관은 비어있을 수 있으며,이 경우 ~~내부에 문자 가 없습니다 . 단일 튜브에는 최대 8 개의 수위 장치가 포함될 수 있습니다.

내부에는 수위가 다른 유한 한 수의 테스트 튜브가 제공됩니다. 가능한 한 최소한의 테스트 튜브에 물을 붓고 결과를 출력해야합니다.

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

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

보시다시피 테스트 튜브는 단일 공간으로 분리됩니다. 빈 튜브는 출력에 표시되지 않아야합니다. 이것은 코드 골프이므로 바이트 수가 가장 적은 코드가 승리합니다.

테스트 사례 : http://pastebin.com/BC0C0uii

행복한 골프!


물을 재배포 할 수 있습니까? 예를 들어 7 + 6이 예제에 유효한 출력입니까?
Martin Ender

@MartinEnder 가능한 한 적은 양의 튜브를 사용해야합니다. 나는이 경우에 허용된다고 생각합니다.
Jacajack

@StewieGriffin 나는 아직 비슷한 것을 보지 못했다. 그래서 그것이 다소 중복이라면 죄송합니다
Jacajack

후행 공백이 허용됩니까?
PurkkaKoodari

더 나은 제목- "최적화 ASCII 테스트 튜브 아기"
Optimizer

답변:



4

자바 스크립트 (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 바이트를 저장해야합니다. 당신은 -1 대신 사용 N 초기화 할 수 있습니다 n>>3그리고 ~n&7^i하나 더 바이트를 저장합니다.
Arnauld

@Arnauld -1아이디어를 주셔서 감사 하지만 아이디어를 개선 할 수있었습니다 replace.
Neil

1
좋은! 나는 1/"\n"진실 하다는 것을 결코 깨닫지 못했습니다.
Arnauld

@Arnauld 글쎄, 그것은 케이크에 여분의 바이트의 착빙이었습니다 ...
Neil

3

펄, 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$%.
변수 이름은 (는) 자기 읽을 수 있도록 ( $%, $@, $:)하지만, 같은 키워드를 허용 x하고for 공백없이 변수 뒤에 작성됩니다.

그것을 실행하려면 :

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 아 맞다, 그것은 많이 설명한다! 감사합니다 :)
Dada

3

비 펀지, 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, 수위가 아닌 다른 영역에 대해서는 0, 수위에 대해서는 1입니다. 따라서 적절한 문자를 출력하기위한 간단한 테이블 조회로 사용할 수 있습니다 (4 행의 시작 부분에서이 테이블을 볼 수 있음).


2

하스켈, 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

파이썬, 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 바이트의 코드에 1 바이트 -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 바이트)

  • (-1 바이트)n||=0 대신 사용n=n||0
  • (+1 바이트)에 대한 malus를 얻었습니다.-n

0

파이썬 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.