ASCII test tüplerini optimize edin


13

Size bir grup ASCII test tüpü verilir, göreviniz kullanılan test tüpü sayısını azaltmaktır.

Her test tüpü şöyle görünür:

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

Açıkçası, ~~su seviyesi. Test tüpü de boş olabilir, bu durumda ~~içinde karakter yoktur . Tek tüp 8 adede kadar su seviyesi ünitesi içerebilir.

İçinde farklı su seviyelerine sahip sınırlı sayıda test tüpü verilir. Suyu mümkün olan en az miktarda test tüpüne dökmeniz ve sonucu vermeniz gerekir.

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

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

Gördüğünüz gibi, test tüpleri tek boşlukla ayrılır. Boş tüpler çıktıda gösterilmemelidir. Bu kod golf, yani en az bayt sayısı ile kod kazanır.

Test örnekleri: http://pastebin.com/BC0C0uii

Mutlu golf!


Suyu da yeniden dağıtabilir miyiz? Örneğin, 7 + 6 örneğiniz için geçerli bir çıktı olur mu?
Martin Ender

@MartinEnder Mümkün olan en az miktarda tüp kullanmalısınız. Bence bu kabul edilebilir.
Jacajack

@StewieGriffin Ben burada benzer bir şey henüz görmedim, bu yüzden bu biraz yinelenen eğer üzgünüm
Jacajack

Sondaki boşluklara izin veriliyor mu?
PurkkaKoodari

Daha iyi başlık - "Optimizer ASCII test tüpü bebekleri"
Doktor

Yanıtlar:



4

JavaScript (ES6), 159 148 bayt

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

Sondaki satır beslemesi çıktılar. Düzenleme: @Arnauld yardımı ile 11 bayt kaydedildi.


s.replace(/~~/g,(_,i)=>n+=9-i/s.indexOf`\n`|0,n=0)4 bayt kaydetmelidir. Bunun yerine n'den -1'e başlatabilir ve bir bayt daha kaydetmek için n>>3ve ~n&7^ituşlarını kullanabilirsiniz.
Arnauld

@Arnauld -1Fikir için teşekkürler ama fikri geliştirebildim replace.
Neil

1
Güzel! Asla 1/"\n"gerçeğin olduğunu fark etmedim.
Arnauld

@Arnauld Peki, sadece kek üzerine krema ilave bir bayt ...
Neil

3

Perl, 150 bayt

149 bayt kod + -nbayrak.

$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üm kodu açıklamayacağım, sadece birkaç şey:
$l+=9-$.for/~~/ggirişte ne kadar su olduğunu sayar.
Kodun ikinci kısmı çıktıyı yazdırır. Fikir, mümkün olduğunca çok dolu tüp ve kalan suyu içeren son tüpü (varsa) koymaktır. Algoritma 4 bölgelerinde yani: birinci su hattı (tüplerin üst) yazdırır: say"|~~| "x$v.($@="| | ")x$r. Geçen tüpün su düzeyine ulaşana kadar Sonra tüplerin boş kısımlarını yazdırmak: say$:=$@x$%for$l%8..6. Geçen tüp su olduğu Ardından seviyesini yazdırın: say$@x$v."|~~|"x$r. Sonra, geri kalan tüm "boş" seviyelerini yazdırın: say$:for 2..$l%8;. Ve son olarak, alt çizgi yazdırmak: say"|__| "x$%.
Değişken adları bu zor okunur hale ( $%, $@, $:) ama gibi anahtar kelimeler için izin verir xvefor değişkenten sonra boşluk bırakmadan yazılacak.

Çalıştırmak için:

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

Bu cevabın ne kadar sürdüğünden pek memnun değilim. Algoritmamdan en iyi şekilde yararlanmaya çalıştım, ancak farklı bir yaklaşım muhtemelen daha kısa olabilir. Yakında üzerinde çalışacağım.


@ TestHolderness Tüm test vakalarını denedim (ve şüphe duyduğum için şimdi tekrar denedim) ve bana iyi geliyor. "Sonuncusu" 3 tüplü olan: 2 su seviyesi 4'te ve 1 su seviyesi 2'de, değil mi? Eğer öyleyse, o zaman denedim ve pastadaki çıktıyla aynı çıktıyı veriyor
Dada

@JamesHolderness Ah doğru, çok şey açıklıyor! Teşekkürler :)
Dada

3

Befunge, 144 138 bayt

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

Çevrimiçi deneyin!

İlk iki satır girişi işler, temel olarak her bir tüpteki seviye işareti olabilecek ilk karakter hariç her şeyi yok sayar. Bu karakterin ASCII değerini alıyoruz, 2'ye ve mod 2'ye bölüyoruz (seviye işaretçisinde olup olmadığımıza bağlı olarak bize 1 veya 0 veriyoruz), bunu satır numarasıyla çarpıyoruz (8'den geriye sayıyor, böylece bize bu tüpün seviye değerini) ve çalışan toplama ekleyin.

Çıktı, esasen üçüncü satırın en sağından başlayarak ikinci iki satırda ele alınır. İlk olarak toplam su seviyesini artı 7'ye 8 bölerek tüp sayısını hesaplıyoruz. Daha sonra tüm tüplerin satırları üzerinde tekrarlarken, bir tüp için belirli bir tüpün ( t , 0'a kadar geri sayım) içinde görüntülenecek karakteri hesaplıyoruz. verilen satır ( r , 8'den 0'a geri sayım) aşağıdaki gibidir:

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

Hesaplanan karakter_türü en alt sıra için (tüpün tabanı) -1, su seviyesi olmayan herhangi bir alan için 0 ve su seviyesi için 1'dir. Böylece, uygun karakterin çıktısı için basit tablo araması olarak kullanılabilir (bu tabloyu 4. satırın başında görebilirsiniz).


2

Haskell, 186 bayt

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

Kullanım örneği:

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

Her satıra bir boşluk ekler. Nasıl çalışır:

              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

Ana ağrı, bir dizgide bir alt dizenin ne sıklıkta meydana geldiğini sayan bir işlevin olmamasıydı. Orada countiçinde Data.Text, ama bunu ithal yolu kararlılığının çok pahalıdır adı çakışmaları bir demet yol açar.


1

Python, 261 bayt

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

Kaçırdığım bir şey varmış gibi hissediyorum. Ayrıca, bir dizi yeni satır boş çıktı için uygunsa, bazı baytları kaybedebilirim. Gibi girdi alır '| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n| | | | | |\n|__| |__| |__|'.


1

Ruby , 139 bayt

(138 bayt kod artı bir bayt -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)}

Çevrimiçi deneyin!

Birkaç açıklama:

Bu program -nanahtar gerektirir .

n - su sayacı.

b- Tüpler oluşturmak için şablon; eşittir"|__| "

i - Boru yapımı sırasındaki akım hattı endeksi.

gsub(/~~/){}- Bu gsubsadece su seviyesini saymayı kötüye kullanır. gsubaslında genişler Kernel.gsub, eşdeğerdir $_.gsub!. Bu, geçerli satırı ( $_) gereksiz yere manipüle eder ; ancak, b=[0,5]yerine daha özlü bir atamaya izin verir b=$_[0,5].

n=n+9-$.- Su seviyesini ölçmek için, ifade geçerli giriş satırı numarasını$. taşıyan önceden tanımlanmış değişkeni kullanır . Bu, açık döngü değişkenini kaybetmeme izin verdi.

b=gsub(/~~/){}[0,5]- en soldaki tüpün altını şablon olarak önbelleğe alır. (Bana “Kahire'de Fil” modeli gibi geliyor, çünkü alt çizgi kazanıyor.)
Tüpün dibinde hiç su gösterilmediğinden, gsuborada olduğumuzda hiçbir şeyin yerini almayacak; bu nedenle sonunda bher zaman eşittir "|__| ".

END{}- Tüm girdi akışı işlendikten sonra çağrılır. Bu fazı hedef tüpleri oluşturmak için kullanıyorum.

i>0??\ :?~- sadece kısaca i > 0 ? " " : "~".

Güncelleme 1: Değişkenler, gsubhile ve END{}aşaması hakkında ayrıntılar eklendi .

Güncelleme 2: (genel olarak ± 0 bayt)

  • (-1 bayt)n||=0 yerine kullann=n||0
  • Malus aldı -n (+1 bayt)

0

Python 3, 404 bayt

Bu program hem ASCII hem de sayı formatlarında su seviyelerine sahip tam çıktıyı oluşturur.

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.