Seberapa mabuk saya dan kapan saya bisa mengemudi lagi?

8

Ini akhir pekan dan apa yang dilakukan cowok-cowok keren di akhir pekan? Minum tentu saja! Tapi tahukah Anda apa yang tidak begitu keren? Minum dan mengemudi. Jadi Anda memutuskan untuk menulis sebuah program yang memberi tahu Anda seberapa dimuatnya Anda dan kapan Anda akan bisa mengemudi lagi tanpa ditarik oleh polisi dan kehilangan lisensi Anda.

Tantangan

Diberikan daftar minuman yang Anda nikmati malam ini, hitung kadar alkohol dalam darah Anda dan waktu Anda harus menunggu sampai Anda dapat naik ke mobil dan pulang.

Memasukkan

Masukan akan menjadi daftar minuman yang Anda miliki malam ini. Ini akan terlihat seperti ini:

4 tembakan minuman keras
1 gelas anggur
2 botol bir
3 gelas air

Kontainer akan selalu berbentuk jamak.

Seperti yang Anda lihat, setiap entri terdiri dari:

  • Jenis minuman (minuman keras, anggur, bir, air)
  • Wadah untuk minuman (gelas, gelas, botol)
  • Jumlah x minuman yang Anda miliki dari jenis itu sebagai bilangan bulat dengan x> 0,

Setiap jenis minuman menambahkan sejumlah alkohol ke darah Anda:

minuman keras -> 0,5 ‰ / 100 ml
bir -> 0,1 ‰ / 100 ml
anggur -> 0,2 ‰ / 100 ml
air -> -0,1 ‰ / 100 ml

Air adalah perkecualian di sini, karena mengeluarkan darah Anda dan menurunkan tingkat alkohol Anda (akan sangat baik jika itu benar-benar bekerja ...).

Setiap wadah memiliki volume tertentu:

tembakan -> 20 ml
kacamata -> 200 ml
botol -> 500 ml

Keluaran

Anda harus menampilkan dua angka:

  • Tingkat alkohol dalam ‰
  • Waktu dalam jam Anda harus menunggu hingga Anda mencapai 0,5 ‰ atau kurang, sehingga Anda dapat mengemudi lagi. Anda kehilangan 0,1 ‰ per jam.

Catatan

  • Tingkat alkohol tidak pernah bisa jatuh di bawah nol.
  • Hal yang sama berlaku untuk waktu tunggu. Jika Anda memiliki 0,5 ‰ atau kurang, hasilkan nol.
  • Urutan minuman tidak masalah, jadi air minum dapat menurunkan kadar alkohol di bawah nol dalam proses perhitungan. Jika tetap ada, Anda harus menggantinya dengan nol.

Tingkat alkohol untuk contoh di atas akan dihitung seperti ini:

4 tembakan minuman keras -> 0,4 ​​‰
1 gelas anggur -> 0,4 ​​‰
2 botol bir -> 1,0 ‰
3 gelas air -> -0,6 ‰

=> 0,4 ​​+ 0,4 + 1 - 0,6 = 1,2 ‰

Untuk mencapai 0,5 ‰ Anda harus kehilangan 0,7 ‰. Anda kehilangan 0,1 ‰ per jam, jadi Anda harus menunggu 7 jam untuk mengemudi lagi.

Aturan

  • Anda dapat mengambil input dalam format apa pun yang Anda inginkan, tetapi Anda harus menggunakan string yang tepat seperti yang diberikan di atas. Anda dapat mengambil angka sebagai bilangan bulat.
  • Anda dapat menampilkan dua angka dalam urutan apa pun, cukup jelaskan yang mana yang Anda gunakan dalam jawaban Anda.
  • Anda dapat mengasumsikan bahwa input akan selalu memiliki setidaknya satu entri.
  • Fungsi atau program lengkap diizinkan.
  • Aturan default untuk input / output.
  • Celah standar berlaku.
  • Ini adalah , sehingga byte-count terendah akan menang. Tiebreak adalah pengiriman sebelumnya.

Uji kasus

Input sebagai daftar string. Menghasilkan tingkat alkohol terlebih dahulu, nilai dipisahkan oleh koma.

["4 tembakan minuman keras", "1 gelas anggur", "2 botol bir", "3 gelas air"] -> 1.2, 7
["10 tembakan minuman keras", "1 botol air"] -> 0,5, 0
["3 gelas anggur", "2 botol minuman keras"] -> 6.2, 57
["6 tembakan bir", "3 gelas air"] -> 0, 0
["10 gelas bir"] -> 2.0, 15

Selamat Coding!

Denker
sumber
1
"Tingkat alkohol tidak akan pernah jatuh di bawah nol." - Apakah susunannya dalam urutan konsesi, atau hanya total? Jadi jika saya memiliki 1 gelas bir, dan kemudian 2 gelas air, dan kemudian 1 gelas bir, haruskah menghasilkan 0% atau 0,5%?
Kuilin Li
1
@ KuilinLi Bukan, pesanan tidak masalah. Saya akan menjelaskan, terima kasih atas komentarnya!
Denker
1
Jadi harus menghasilkan 0, dan kadar alkohol secara teknis dapat turun di bawah nol di tengah minum? Karena kalau tidak, kita tidak dapat mengetahui kapan airnya diminum jika susunan mengandung air ... Kita bahkan dapat berasumsi bahwa, jika susunan berisi air, kita akan minum air pertama, dan itu tidak akan berpengaruh pada apa pun.
Kuilin Li
1
@ KuilinLi, saya sudah menjelaskan tantangannya sekarang. Tingkat alkohol dapat jatuh di bawah nol dalam proses perhitungan, Anda hanya perlu membulatkannya menjadi nol jika tetap di sana.
Denker
7
Saya tidak minum, jadi entri sayafunction drive(a) { if (a.every(v=>/water/.test(v))) return [0, 0]; throw new TeetotalException; }
Neil

Jawaban:

1

Javascript (ES6), 109

Mengambil input sebagai array dari array string / integer mis

[[4, "shots", "booze"],
[1, "glasses", "wine"],
[2, "bottles", "beer"],
[3, "glasses", "water"]]

Output ke array sederhana mis[1.2, 7]

a=>(b=0,c={s:2,g:20,b:50,o:2,e:10,i:5,a:-10},a.map(([d,e,f])=>b+=d*c[e[0]]/c[f[1]]),g=b>0?b:0,[g/10,g?g-5:0])

Dijelaskan

a => (
b = 0,                                           // Counter For Alcohol Level
c = {s:2, g:20, b:50, o:2, e:10, i:5, a:-10},    // Look up for values
a.map(                                           // Loops over array
  ([d, e, f]) =>                                 // Sets d,e,f to respective array indexes 
     b += d * c[e[0]] / c[f[1]]                  // Increases Level by values from lookup
  ),
g = b > 0 ? b : 0,                               // If Level is lower than 0 make it = 0
[g / 10, g ? g - 5 : 0])                         // Output: Level / 10 and Level - 5 bound to 0
reubn
sumber
Dimainkan dengan baik tetapi tidak selalu valid: try[[3,"shots", "booze"]]
edc65
@ edc65 Good Catch!
Reubn
Hanya perlu sedikit penyesuaian dan masih jauh lebih baik daripada milik saya
edc65
6

TSQL, 301 , 299 , 219 , 206 Bytes

Input masuk ke tabel temp #I(Anda mengatakan format apa saja :)

SELECT * INTO #I FROM (
  VALUES
    (4,'shots','booze')
   ,(1,'glasses','wine')
   ,(2,'bottles','beer')
   ,(3, 'glasses','water')
) A (Q, V, N)

Kode:

SELECT IIF(L<0,0,L),IIF(10*L-.5<0,0,10*L-.5)FROM(SELECT SUM(Q*S*P)L FROM(VALUES('bo%',.5),('be%',.1),('wi%',.2),('wa%',-.1))A(W,S),(VALUES('s%',.2),('g%',2),('b%',5))B(X,P),#I WHERE N LIKE W AND V LIKE X)A;

Terima kasih atas ide untuk memperbaikinya, Micky T :)

Liesel
sumber
Untuk 2012+ Anda bisa menggunakan IIFfungsi alih-alih CASEpernyataan untuk beberapa byte
MickyT
1
Anda juga bisa mengubah nama kolom Anda di subqueries untuk menghindari keharusan untuk memenuhi syarat maka dalam klausa bergabung misalnya JOIN(SELECT .. )A(Y,S)ON Y=Ndan (L+ABS(L))/2,10*((L-.5+ABS(L-.5))/2)lebih pendek dari fungsi IIF yang disebutkan sebelumnya. Anda juga dapat menghemat sedikit jika Anda melihat melakukan cross join pada nilai-nilai untuk ukuran dan kekuatan. mis.SELECT V,N,Q*S FROM(VALUES(...))A(N,S),(VALUES(...)B(V,Q)
MickyT
3

JavaScript (ES6), 131

a=>a.map(s=>([a,b,c]=s.split` `,t+=a*[50,20,2]['bgs'.search(b[0])]*~-'0236'['aeio'.search(c[1])]),t=0)&&[t>0?t/100:0,t>50?t/10-5:0]

Kurang golf

a=>(
  t=0,
  a.map(s=>(
    [a,b,c] = s.split` `,
    t += a * [50,20,2]['bgs'.search(b[0])] // char 0 is unique
           * [-1,1,2,5]['aeio'.search(c[1])] // char 1 is unique 
           // golfed: add 1 to get a string of dingle digits, the sub 1 using ~-
    )
  ),
  [ t>0 ? t/100 : 0, t>50 ? t/10-5 : 0]
)
edc65
sumber
1

Perl, 133 119 + 3 = 136 122 byte

%u=(o,.5,e,.1,i,.2,a,-.1,g,2,b,5,s=>.2);/(\d+) (.).* .(.)/;$x+=$1*$u{$2}*$u{$3}}{$_=($x>0?$x:0).$".($x-.5>0?$x-.5:0)*10

Untuk dijalankan perl -p. Mengambil input berorientasi garis pada STDIN, menghasilkan output pada STDOUT.

Versi kurang golf:

# char->number conversion table
# declared using barewords except for 's', which can't be a bareword
# because it's a keyword
%u=(o,.5, e,.1, i,.2, a,-.1, g,2, b,5, s=>.2);

# extract the number, first letter of first word, second letter of
# second word
/(\d+) (.).* .(.)/;

# do unit conversion and multiply up all factors
$x += $1 * $u{$2} * $u{$3}

# hack for -p to produce an END { ... print } block
}{

# format output
$_ = ($x > 0 ? $x : 0) . $" . ($x-.5 > 0 ? $x-.5 : 0)*10

Terima kasih kepada dev-null untuk saran menghemat 11 byte.

David Morris
sumber
@ dev-null terima kasih! Saya pikir fungsi masuk akal untuk pemendekan menengah, dan saya lupa untuk memeriksa apakah itu masih membantu.
David Morris
Jika Anda selalu mendapatkan input yang valid maka Anda dapat mengubah \dke.
andlrc
Apakah Anda ingin menambahkan contoh menjalankan program, sehingga jelas format input dan output yang Anda gunakan?
Denker