Tối ưu hóa ống nghiệm ASCII


13

Bạn được tặng một loạt các ống nghiệm ASCII, nhiệm vụ của bạn là giảm số lượng ống nghiệm được sử dụng.

Mỗi ống nghiệm trông như thế này:

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

Rõ ràng, ~~là mực nước. Ống nghiệm cũng có thể trống, trong trường hợp không có ~~ký tự bên trong. Ống đơn có thể chứa tới 8 đơn vị mực nước.

Bạn được cung cấp số lượng hữu hạn của các ống nghiệm với mức nước khác nhau bên trong. Bạn phải đổ nước vào số lượng ống nghiệm ít nhất có thể và đưa ra kết quả.

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

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

Như bạn có thể thấy, các ống nghiệm được phân tách bằng không gian đơn. Các ống rỗng không nên được hiển thị trong đầu ra. Đây là mã golf, vì vậy mã có số byte ít nhất sẽ thắng.

Các trường hợp thử nghiệm: http://pastebin.com/BC0C0uii

Chúc bạn chơi golf vui vẻ!


Chúng ta cũng có thể phân phối lại nước? Ví dụ: 7 + 6 sẽ là đầu ra hợp lệ cho ví dụ của bạn?
Martin Ender

@MartinEnder Bạn nên sử dụng số lượng ống ít nhất có thể. Tôi nghĩ đó là chấp nhận được trong trường hợp này.
Jacajack

@StewieGriffin Tôi chưa thấy bất cứ điều gì tương tự ở đây, vì vậy nếu đó là một bản sao thì tôi xin lỗi
Jacajack

Là khoảng trắng dấu vết được phép?
PurkkaKoodari

Tiêu đề tốt hơn - "Trình tối ưu hóa em bé ống nghiệm ASCII"
Trình tối ưu hóa

Câu trả lời:



4

JavaScript (ES6), 159 148 byte

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?`__`:`  `:`~~`)

Xuất ra một linefeed trailing. Chỉnh sửa: Đã lưu 11 byte với một số trợ giúp từ @Arnauld.


s.replace(/~~/g,(_,i)=>n+=9-i/s.indexOf`\n`|0,n=0)nên tiết kiệm 4 byte. Thay vào đó, bạn có thể muốn khởi tạo n thành -1 và sử dụng n>>3~n&7^ilưu thêm một byte.
Arnauld

@Arnauld Cảm ơn -1ý tưởng nhưng tôi đã có thể cải thiện replaceý tưởng.
Neil

1
Đẹp! Tôi không bao giờ nhận ra 1/"\n"là sự thật.
Arnauld

@Arnauld Chà, nó chỉ là một byte thêm icing trên bánh ...
Neil

3

Perl, 150 byte

149 byte mã + -ncờ.

$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$%

Tôi sẽ không giải thích tất cả các mã, chỉ một vài điều:
$l+=9-$.for/~~/gđếm lượng nước trong đầu vào.
Phần thứ hai của mã in đầu ra. Ý tưởng là đặt càng nhiều ống càng đầy càng tốt, và ống cuối cùng chứa nước còn lại (nếu có). Vì vậy, thuật toán gồm 4 phần: in dòng nước đầu tiên (đầu ống) : say"|~~| "x$v.($@="| | ")x$r. Sau đó, in các phần trống của ống cho đến khi chúng ta đạt đến mức nước của ống cuối cùng : say$:=$@x$%for$l%8..6. Sau đó in mức nước ống cuối cùng là : say$@x$v."|~~|"x$r. Sau đó, in tất cả các mức "trống" còn lại : say$:for 2..$l%8;. Và cuối cùng, in dòng dưới cùng : say"|__| "x$%.
Các tên biến làm cho nó khó đọc ( $%, $@, $:) nhưng cho phép các từ khóa như xfor được viết sau biến không có khoảng trắng.

Để chạy nó:

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$%' <<< "|  | |  | |  | |  |
|  | |  | |  | |  |
|  | |~~| |  | |  |
|~~| |  | |  | |  |
|  | |  | |  | |  |
|  | |  | |  | |  |
|  | |  | |~~| |  |
|  | |  | |  | |  |
|__| |__| |__| |__| "

Tôi không hài lòng lắm với câu trả lời này trong bao lâu. Tôi đã cố gắng tận dụng tốt nhất thuật toán của mình, nhưng một cách tiếp cận khác có thể ngắn hơn. Tôi sẽ cố gắng làm việc với nó sớm thôi.


@JamesHoldiness Tôi đã thử tất cả các trường hợp thử nghiệm (và đã thử lại ngay bây giờ vì bạn nghi ngờ tôi) và nó có vẻ tốt với tôi. "Cái cuối cùng" là cái có 3 ống: 2 với mực nước ở 4 và 1 với nước ở cấp 2, phải không? Nếu vậy, thì tôi đã thử nó và nó cho đầu ra tương tự như trên pastbin
Dada

@JamesHoldiness Oh phải, nó giải thích rất nhiều! Cảm ơn :)
Dada

3

Befunge, 144 138 byte

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:#^_@

Hãy thử trực tuyến!

Hai dòng đầu tiên xử lý đầu vào, về cơ bản bỏ qua mọi thứ trừ ký tự đầu tiên trong mỗi ống có thể là điểm đánh dấu mức. Chúng tôi lấy giá trị ASCII của ký tự đó, chia cho 2 và mod 2 (cho chúng tôi 1 hoặc 0 tùy thuộc vào việc chúng tôi có đánh dấu cấp độ hay không), nhân số đó với số hàng (đếm ngược từ 8, do đó cho chúng tôi giá trị mức cho ống đó) và thêm nó vào tổng số đang chạy.

Đầu ra được xử lý trên hai dòng thứ hai, về cơ bản bắt đầu ở phía bên phải của dòng thứ ba. Trước tiên, chúng tôi tính toán số lượng ống bằng cách lấy tổng mực nước cộng với 7 chia cho 8. Sau đó, khi lặp qua các hàng của tất cả các ống, chúng tôi tính toán ký tự hiển thị bên trong một ống cụ thể ( t , đếm ngược đến 0) cho a hàng đã cho ( r , đếm ngược từ 8 xuống 0) như sau:

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

Char_type được tính toán là -1 cho hàng đáy (đáy của ống), 0 cho bất kỳ khu vực nào khác không phải là mực nước và 1 cho mực nước. Do đó, nó có thể được sử dụng như tra cứu bảng đơn giản cho ký tự phù hợp để xuất ra (bạn có thể thấy bảng này ở đầu dòng 4).


2

Haskell, 186 byte

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

Ví dụ sử dụng:

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

Đặt một không gian dấu trên mỗi dòng. Làm thế nào nó hoạt động:

              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

Nỗi đau chính là thiếu chức năng tính tần suất xuất hiện của một chuỗi con trong chuỗi. Có counttrong Data.Text, nhưng nhập khẩu nó dẫn đến một loạt các xung đột tên đó là cách quá đắt để quyết tâm.


1

Python, 261 byte

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

Tôi cảm thấy như có gì đó tôi đang thiếu. Ngoài ra, nếu một loạt các dòng mới có thể truy cập được cho đầu ra trống, tôi có thể mất một số byte. Đưa đầu vào như thế nào '| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n|__| |__| |__|'.


1

Ruby , 139 byte

(138 byte mã cộng với một byte cho -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)}

Hãy thử trực tuyến!

Một vài lời giải thích:

Chương trình này yêu cầu -nchuyển đổi.

n - quầy nước.

b- Mẫu để xây dựng ống; bằng"|__| "

i - Chỉ số dòng hiện tại trong quá trình xây dựng ống.

gsub(/~~/){Sầu }- Điều này lạm dụng gsubđể chỉ đơn giản là đếm mực nước. gsubthực sự mở rộng đến Kernel.gsub, tương đương với $_.gsub!. Điều này không cần thiết thao túng dòng hiện tại ( $_); Tuy nhiên, nó cho phép cho một phân súc tích hơn b=... [0,5]thay vì b=$_[0,5].

n=n+9-$.- Để đo mực nước, biểu thức sử dụng biến được xác định trước $., mang số dòng đầu vào hiện tại . Điều này cho phép tôi mất biến vòng lặp rõ ràng.

b=gsub(/~~/){Tiết }[0,5]kiệm - lưu trữ dưới cùng của ống ngoài cùng bên trái làm mẫu. (Cảm thấy hơi giống với Voi voi trong mẫu Cairo Cairo đối với tôi vì dòng dưới cùng thắng.)
Vì đáy ống không bao giờ có nước, nên gsubsẽ không thay thế bất cứ thứ gì khi chúng tôi ở đó; Vì thế cuối cùng, bluôn luôn bằng "|__| ".

END{... }- Gets gọi sau khi input stream toàn bộ đã được xử lý. Tôi sử dụng giai đoạn này để xây dựng các ống mục tiêu.

i>0??\ :?~- chỉ đơn giản là tay ngắn cho i > 0 ? " " : "~".

Cập nhật 1: Thêm chi tiết về các biến, các gsubthủ đoạn gian trá và END{... }pha.

Cập nhật 2: (± 0 byte tổng thể)

  • Sử dụng n||=0thay vì n=n||0 (-1 byte)
  • Lấy malus cho -n (+1 byte)

0

Python 3, 404 byte

Chương trình này tạo ra đầu ra dự định đầy đủ với mực nước ở cả định dạng ASCII và số.

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.