22
\$\begingroup\$

Background

It's late Friday afternoon and you and your friends decide to hit the pub later that evening, but before going to the pub you figure you should have a few beverages. However, things escalate quickly; your friend Shaddock Pamplemousse won the lottery earlier this week and decided to bring crates upon crates with different beverages. The security at the pub is very strict, and if you overconsume before trying to enter the premises you are not allowed inside. You are all programmers though - so you figure things will turn out great anyway.

Challenge

You need to program an alcohol meter which outputs truthy/falsy if you're above/below the reasonable pub limit. Before you go down to the pub you enter the amount and beverage type you've consumed during the evening to stdin which your measurement program reads. If it outputs truthy, you are above the pub limit and stay at home. If it outputs falsy, you're good to go.

Input

One integer greater than 0 which represents your body weight in kilograms followed by a newline. This input is followed by a series of one digit amounts and beverages on the following form:

<amount><amount type>o<beverage type>

For one bottle of beer this will look like:

1Bob

Each input is separated by a space.

Input specification

Each beverage has a unit which correspond to the impact caused by it. If you consume more units than your weight divided by two the pub is not an option anymore.

(This may or may not reflect reality)

The following are valid beverages and the corresponding alcoholic units of the beverage:

  • Beer: b, 1 unit

  • Energy drink: e, 0 units

  • Hot sauce: h, 2 units (strong stuff)

  • Juice (made of organic fruits etc): j, 0 units

  • Rum: r, 6 units

  • Tequila: t, 7 units

  • Vodka: v, 6 units

  • Wine: w, 3 units

There are different amount types:

  • Bottle: B

  • Crate: C

  • Glass: G

  • Keg: K

  • Sip: S

Each amount type has a multiplier which multiplies the alcoholic units of the beverage contained in it:

  • Bottle: 3

  • Crate: 25

  • Glass: 2

  • Keg: 50

  • Sip: 0.2

Output

Your program shall output truthy/falsy to stdout if the amount consumed is above/below your body weight divided by 2. If the amount consumed is equal to your weight divided by 2, you should output falsy.

Samples of possible input and output

Input

70
1Bob 3Soj

Output

False

Input

2
1Cov

Output

1

Input

50
1Cob

Output

0

Input

100
4Gow 1Koe 1Bov 1Gow 2Sot

Output

True

The shortest program in bytes wins!

\$\endgroup\$
  • 1
    \$\begingroup\$ 1. It seems that the o is a format character, though you've not said so specifically. You should clarify this (as o also refers to olive oil.) 2. What do we output if we are exactly on the limit? or doesn't it matter? \$\endgroup\$ – Level River St Nov 12 '15 at 20:42
  • 1
    \$\begingroup\$ Good call; I totally missed that. I'm removing olive oil (who drinks that anyway?) Below or equal to the limit should output falsy. I'll add that. \$\endgroup\$ – sweerpotato Nov 12 '15 at 20:52
  • 1
    \$\begingroup\$ Will there ever be more than one digit of drink? Eg, 43Gow? \$\endgroup\$ – Morgan Thrapp Nov 12 '15 at 22:00
  • 6
    \$\begingroup\$ +1 good question, but it's Friday afternoon and I need to go out for a beer. Maybe Monday:) \$\endgroup\$ – MickyT Nov 13 '15 at 2:33
  • 1
    \$\begingroup\$ I intended for it to be any amount really - except for negative amounts. I didn't think that would come off as ambiguous. I realize if I change this it will invalidate your answer, and that's not how we do things. Amount will be clarified as one digit. \$\endgroup\$ – sweerpotato Nov 13 '15 at 7:24

12 Answers 12

4
\$\begingroup\$

CJam, 53 bytes

6:B50:C2*:K4:G.4:S];q"behjrtvwo ""10206763*"er~*]:-U<

Try it online in the CJam interpreter.

How it works

6:B          e# Push 6 and save it in B.
50:C         e# Push 50 and save it in C.
2*:K         e# Multiply by 2 to push 100 and save it in K.
4:G          e# Push 4 and save it in G.
.4:S         e# Push 0.4 and save it in S.
             e#
             e# The letters representing the types will now push its doubled
             e# (to avoid diving the weight by 2) associated multiplier.
];           e# Clear the stack.
q            e# Read all input.
"behjrtvwo " e# Push the string of beverages, concatenated with "o ".
"10206763*"  e# Push the string of associated units of alcohol and '*'.
er           e# Transliterate. This replaces each beverage letter with the
             e# associated units of alcohol, and each 'o' and ' ' with '*'.
             e#
             e# For example, the input
             e# 70
             e# 1Bob 3Soj
             e# is transformed into
             e# 70
             e# 1B*1*3S*0
             e#
~            e# Evaluate the resulting string.
             e#
             e# For the example this does the following:
             e#   + Push 70.
             e#   + Push 1, push 6, multiply, push 1, multiply.
             e#   + Push 3, push 0.4, multiply, push 0.
             e#
*            e# Multiply the last two (for the lack of a trailing space).
]            e# Collect all results in an array.
:-           e# Reduce by subtraction; subtract all other elements from the
             e# first element (body weight).
U<           e# Compare the result with 0.
\$\endgroup\$
8
\$\begingroup\$

Python 3, 131

Now we're golfing with snakes!

Saved 18 bytes thanks to shebang.
Saved 4 more bytes thanks to DSM.
Saved a lot of bytes thanks to tzaman.

Many thanks to tzaman for his brilliant trick of abusing .find() returning -1 if it doesn't find a value.

Currently this assumes this drink format is exactly the way it's stated in the challenge, eg, only 1 digit worth of each drink.

w=input()
print(sum([6,50,4,100,.4]['BCGKS'.find(b)]*int(a)*int('1267730'['bhrtvw'.find(v)])for a,b,_,v in input().split())>int(w))
\$\endgroup\$
  • \$\begingroup\$ I think it may be good if you dropped the dicts and did everything in the print statement. So, remove m and replace the m[p[-1]] bit with [3,25,2,50,.2]['BCGKS'.find(p[-1])], and the same with d. I got down to 168 with those changes to your code. \$\endgroup\$ – Kade Nov 12 '15 at 22:10
4
\$\begingroup\$

Minkolang 0.11, 59 bytes

126763355*25l*2l$:"SKGCBwvtrhb"m(0pI)n(no0qoxo0q**2*-$I)`N.

Try it here.

Explanation

126763355*25l*2l$:    Pushes the values of the characters
"SKGCBwvtrhb"         Pushes the characters themselves
m                     Merge; interleaves the first and second halves of the stack
(                     Open while loop
 0p                   Put character's value in character's place in the codebox
   I)                 Close while loop when stack is empty
n                     Read in integer (weight)
(                     Open while loop
 n                    Read in integer, ignoring any non-numeric characters
  o0q                 Read in character and get its value from the codebox
     ox               Read in character and dump it
       o0q            Read in character and get its value from the codebox
          **          Multiply the three numbers together
            2*-       Multiply by 2 and subtract from weight
               $I)    Close while loop when input is empty
`                     1 if less than 0, 0 otherwise
 N.                   Output as integer and stop.
\$\endgroup\$
  • \$\begingroup\$ I guess CJam is getting outdated... I need to finish my language then \$\endgroup\$ – anOKsquirrel Nov 12 '15 at 23:18
  • \$\begingroup\$ @anOKsquirrel: Or rather, you just haven't golfed it enough. :) \$\endgroup\$ – El'endia Starman Nov 12 '15 at 23:18
  • \$\begingroup\$ Or rather, both. :P \$\endgroup\$ – anOKsquirrel Nov 12 '15 at 23:20
  • \$\begingroup\$ No, actually, I'm just bad :p \$\endgroup\$ – anOKsquirrel Nov 12 '15 at 23:26
3
\$\begingroup\$

CJam, 54 bytes

ldlS/{A,s"CbretjvwSBK"+f#A,[25X6T7T6Z.2Z50Y]+f=:*-}/0<

Bit fiddly and probably suboptimal, but I think this works okay. Try it online.

Explanation

ld             Read first line, convert to double
lS/            Read second line, split by space
{...}/         For each item in the second line...
  A,s"..."+f#    Get index in "0123456789CbretjvwSBK", or -1 if not found
  A,[...]+f=     Index into [0 1 2 3 4 5 6 7 8 9 25 1 6 0 7 0 6 3 0.2 3 50 2]
  :*             Take product
  -              Subtract from weight
0<             Check if < 0

Note that the numeric array has 2 at the end, meaning that Gho, which are missing from the first string, get mapped to 2.

\$\endgroup\$
2
\$\begingroup\$

CJam, 77

qN%~S%{:BW="behjrtvw"\#10206773s:~\=[3 25 2 50 .2]"BCGKS"B-3=#=*1mO}%:+\~2/\>
\$\endgroup\$
2
\$\begingroup\$

VBA, 251 bytes

Function k(x) As Boolean:q=Split(x):g="b1e0h2j0r6t7v6w3":h="B03C25G02K50S.2":For i=1 To UBound(q):j=j+Left(q(i),Len(q(i))-3)*Mid(h,InStr(h,Mid(Right(q(i),3),1,1))+1,2)*Mid(g,InStr(g,Mid(Right(q(i),3),3,1))+1,1):Next i:If q(0)/2<j Then k=1
End Function

Using : rather then Newline doesn't make it shorter, But it does look more golfy!

Readable Format

Function b(x) As Boolean
q = Split(x)
g = "b1e0h2j0r6t7v6w3"
h = "B03C25G02K50S.2"
For i = 1 To UBound(q)
j = j + Left(q(i), Len(q(i)) - 3) * _          'Left most digits would be the Quantity
Mid(h, InStr(h, Mid(Right(q(i), 3), 1, 1)) + 1, 2) * _  'Find the Container value in h
Mid(g, InStr(g, Mid(Right(q(i), 3), 3, 1)) + 1, 1)      'Find the Drink value in g
Next i
If q(0) / 2 < j Then b = 1 'Checks if Drunk or not
End Function

Pretty Sure this can be golfed. my String Manipulation with Mid(Right()) seems excessively wordy, But running the array though StrReverse makes it longer. If we assume you only drink 0-9 of any particular drink at a time we can save a handful of bytes

Take input as one string with weight separated by a space as VBA dose not support multi line input

\$\endgroup\$
2
\$\begingroup\$

Ruby, 153 bytes

I need to get rid of the gsubs somehow

w=gets.to_i;$><<(eval(gets.chars{|c|c[/[0-9]/]!=p ? ($_[c]+='*'):0}.tr('behjrtvwo BG','10206763*+32').gsub('C','25').gsub('K','50').gsub('S','0.2'))>w/2)
\$\endgroup\$
2
\$\begingroup\$

JavaScript, 131 134 139 bytes

This is a full program and basically an adaption of my PHP answer:

for(c=prompt,b=c(a=c(s=i=0));b[i];i+=2)s+=b[i++]*{B:3,C:25,G:2,K:50,S:.2}[b[i++]]*{b:1,h:2,r:6,t:7,v:6,w:3}[b[++i]]||0;alert(s>a/2)

It reads two values using prompt and alerts the result as [true|false].


Edits

  • Saved 5 bytes by using a logical expression ||0 instead of declaring the beverages with 0 units. Thanks to user81655.
  • Saved 3 bytes by storing prompt in a variable and shortening the initialization. Thanks to Stefnotch.
\$\endgroup\$
  • 1
    \$\begingroup\$ You could save 6 bytes by changing ,e:0,j:0}[b[++i]] to }[b[++i]]|0. \$\endgroup\$ – user81655 Nov 14 '15 at 10:19
  • \$\begingroup\$ @user81655 Yesterday I was thinking, how to get rid of those 0-values. Well, I didn't think of that. Had to use || instead of the bitwise operator. Still 5 bytes less. Thanks. \$\endgroup\$ – insertusernamehere Nov 14 '15 at 10:27
  • \$\begingroup\$ No problem. I forgot about the possible non-integer values. \$\endgroup\$ – user81655 Nov 14 '15 at 10:46
  • 1
    \$\begingroup\$ for(s=i=0,a=prompt(),b=prompt(); can be changed to: for(c=prompt,b=c(a=c(s=i=0)); \$\endgroup\$ – Stefnotch Nov 14 '15 at 18:19
  • 1
    \$\begingroup\$ @Stefnotch That's clever. I like it. Thanks for saving 3 bytes. \$\endgroup\$ – insertusernamehere Nov 15 '15 at 16:42
1
\$\begingroup\$

bash (+ bc + GNU sed), 200 196 194 bytes

read x
read y
y="$(sed 's/^/((/;s/$/))/;s/ /)+(/g;s/o/*/g;s/b/1/g;s/[ej]/0/g;s/h/2/g;s/[rv]/6/g;s/w/3/g;s/t/7/g;s/B/*3/g;s/C/*25/g;s/G/*2/g;s/K/*50/g;s/S/*0.2/g'<<<"$y")"
echo "$y>$x/2"|bc -l
\$\endgroup\$
1
\$\begingroup\$

Javascript, 159 bytes

function b(t){return a={B:3,C:25,G:2,K:50,S:.2,b:1,h:2,w:3,r:6,v:6,t:7},t.split(/\W/).reduceRight(function(t,n,r){return r?n[0]*a[n[1]]*a[n[3]]+t||t:t>n/2},0)}

Since Javascript requires a library to access STDIN, this code is just a function that accepts the entirety of the input, i.e. b("100\n4Gow 1Koe 1Bov 1Gow 2Sot")

\$\endgroup\$
  • 1
    \$\begingroup\$ As a note: prompt() is generally accepted as a valid alternative to STDIN in JavaScript. \$\endgroup\$ – insertusernamehere Nov 13 '15 at 23:24
  • 1
    \$\begingroup\$ You could save 30 bytes by going ES6 and using the arrow-operator: b=t=>(a={B:3,C:25,G:2,K:50,S:.2,b:1,h:2,w:3,r:6,v:6,t:7},t.split(/\W/).reduceRight((t,n,r)=>r?n[0]*a[n[1]]*a[n[3]]+t||t:t>n/2,0)). \$\endgroup\$ – insertusernamehere Nov 13 '15 at 23:44
1
\$\begingroup\$

Python 3, 157 bytes

n,l,d,u=int(input()),input(),"behjrtvwBCGKS",[1,0,2,0,6,7,6,3,3,25,2,50,.2]
print(sum(map(lambda x:int(x[0])*u[d.find(x[1])]*u[d.find(x[3])],l.split()))>n/2)
\$\endgroup\$
1
\$\begingroup\$

PHP, 163 169 bytes

for($a=fgets(STDIN),$b=fgets(STDIN),$v=[b=>1,h=>2,r=>6,t=>7,v=>6,w=>3,B=>3,C=>25,G=>2,K=>50,S=>.2];$b[$i];$i+=2)$s+=$b[$i++]*$v[$b[$i++]]*$v[$b[++$i]];echo$s>$a/2;

Outputs 1 or nothing, works for all test cases.


I still wonder what this hot sauce is, having 2 units.


Edits

  • Saved 6 bytes by merging the two arrays for drinks and multiplier and by removing 0 from 0.2.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.