私はどのくらい酔っていますか、またいつ運転できますか?


8

それは週末です、そして週末にクールな人は何をしていますか?もちろん飲みます!しかし、あなたはそれほどクールではないものを知っていますか?飲む運転。それで、あなたはあなたがどれほどの負荷がかかっているか、そしていつあなたが警官に引っ張られてあなたの免許を失うことなく再び運転することができるかを知らせるプログラムを書くことに決めました。

チャレンジ

今夜あなたが楽しんだ飲み物のリストを考えて、あなたの血中アルコール濃度と、あなたがあなたの車に飛び乗って家に帰れるまで待つ必要がある時間を計算してください。

入力

入力は、今夜あなたが飲んだ飲み物のリストになります。これは次のようになります。

4ショット酒
グラスワイン1杯
ビール2本
3杯の水

コンテナは常に複数になります。

ご覧のとおり、各エントリは次の要素で構成されています。

  • 飲み物の種類(酒、ワイン、ビール、水)
  • 飲み物の容器(ショット、グラス、ボトル)
  • x> 0の整数としてそのタイプの飲み物の量x、

ドリンクの種類ごとに、一定量のアルコールが血液に追加されます。

酒-> 0.5‰/ 100 ml
ビール-> 0.1‰/ 100 ml
ワイン-> 0.2‰/ 100 ml
水-> -0.1‰/ 100 ml

水はあなたの血を薄くし、あなたのアルコールレベルを下げるので、水はここでは例外です(それが実際にうまくいけばとてもいいでしょう...)。

各コンテナには特定の容量があります:

ショット-> 20 ml
グラス-> 200 ml
ボトル-> 500 ml

出力

次の2つの数値を出力する必要があります。

  • inのアルコールレベル
  • 0.5‰以下になるまで待機する必要がある時間単位の時間。これにより、再び運転できます。1時間あたり0.1 loose緩みます。

ノート

  • アルコールレベルは決してゼロを下回ることはありません。
  • 待ち時間も同様です。0.5‰以下の場合は、ゼロを出力します。
  • 飲み物の順序は関係ないので、飲料水は計算の過程でアルコールレベルをゼロ未満に下げる可能性があります。残っている場合は、ゼロに置き換える必要があります。

上記の例のアルコールレベルは次のように計算されます。

4ショット酒-> 0.4‰
1杯のワイン-> 0.4‰
ビール2本-> 1.0‰
3杯の水-> -0.6‰

=> 0.4 + 0.4 + 1-0.6 = 1.2‰

0.5 reachに到達するには、0.7 looseを緩める必要があります。1時間あたり0.1 looseを失うため、再び運転するには7時間待つ必要があります。

ルール

  • 入力は任意の形式で取得できますが、上記のとおり正確な文字列を使用する必要があります。あなたは整数として数を取ることができます。
  • 2つの数値は任意の順序で出力できます。回答でどちらを使用するか明確にしてください。
  • 入力には常に少なくとも1つのエントリがあると想定できます。
  • 機能または完全なプログラムが許可されています。
  • 入力/出力のデフォルトのルール
  • 標準の抜け穴が適用されます。
  • これはなので、最小のバイト数が優先されます。タイブレーカーは以前の提出です。

テストケース

文字列のリストとして入力します。アルコールレベルを最初に出力します。値はカンマで区切られます。

["4ショットの酒"、 "1グラスのワイン"、 "2ボトルのビール"、 "3グラスの水"]-> 1.2、7
["10ショットの酒"、 "1ボトルの水"]-> 0.5、0
["3グラスのワイン"、 "2ボトルの酒"]-> 6.2、57
["6ショットビール"、 "3杯の水"]-> 0、0
["10杯のビール"]-> 2.0、15

ハッピーコーディング!


1
「アルコールレベルは決してゼロを下回ることはありません。」-アレイは譲許の順ですか、それとも合計ですか?それで、私がビールを1ショット、次に水を2ショット、そしてビールを1ショット持っている場合、それは0%または.5%を出力する必要がありますか?
Kuilin Li 2016

1
@KuilinLi違います、順序は関係ありません。コメントありがとうございます。
デンカー、2016

1
それで、それは0を出力するはずであり、アルコールレベルは技術的には飲酒の途中でゼロを下回ることがありますか?そうでなければ、アレイに水が含まれている場合、いつ水が飲まれたかを知る方法がありません...アレイに水が含まれている場合、最初に水を飲むことになると想定することもできます。何でも。
Kuilin Li 2016

1
@KuilinLi私は今チャレンジでそれを明確にしました。計算の過程でアルコールレベルがゼロを下回る場合があります。それが残っている場合は、ゼロに丸める必要があります。
Denker

7
私は飲まないので、私のエントリーはfunction drive(a) { if (a.every(v=>/water/.test(v))) return [0, 0]; throw new TeetotalException; }
Neil

回答:


1

JavaScript(ES6)、109

文字列/整数の配列の配列として入力を受け取ります。

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

単純な配列への出力など[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])

説明した

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

よく再生されますが、常に有効であるとは限りません。試してください[[3,"shots", "booze"]]
edc65

@ edc65グッドキャッチ!
2016

わずかな調整が必要ですが、それでも私のものよりずっと優れています
edc65

6

TSQL、301299219、206バイト

入力は一時テーブルに入ります#I(あなたは任意のフォーマットを言った:)

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

コード:

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;

それを改善するためのアイデアをありがとう、ミッキーT :)


2012+ IIFでは、CASE一部のバイトに対してステートメントではなく関数を使用できます
MickyT

1
また、サブクエリで列名を変更して、結合句で修飾する必要がないようにすることもできます。たとえばJOIN(SELECT .. )A(Y,S)ON Y=N(L+ABS(L))/2,10*((L-.5+ABS(L-.5))/2)前述のIIF関数よりも短いです。サイズと強度の値でクロス結合を行うと、少し節約できます。例SELECT V,N,Q*S FROM(VALUES(...))A(N,S),(VALUES(...)B(V,Q)
MickyT 2016

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]

ゴルフが少ない

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]
)

1

Perl、133 119 + 3 = 136 122バイト

%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

で実行しperl -pます。STDINで行指向の入力を取り、STDOUTで出力を生成します。

ゴルフの少ないバージョン:

# 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

11バイトを節約する提案をしてくれたdev-nullに感謝します。


@ dev-nullありがとう!中間の短縮にはこの機能は理にかなっていると思いますが、それがまだ効果があるかどうかを確認するのを忘れていました。
David Morris

あなたは、常に有効な入力を取得した場合、あなたは変更することができます\d.
andlrc

プログラムの実行例を追加して、使用する入力形式と出力形式を明確にしていただけませんか?
デンカー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.