Santa's Decision

29

0

Santa's Decision:

In this challenge, you will help Santa Claus decide whether somebody on their list has been naughty or nice, and subsequently get coal or toys.

But unfortunately, Santa is unorganised, in some of his entries, the naughty, nice and name fields are in the wrong order.

Input

Input will come in the following, interchangeable format:

  • the person's name (cannot contain a colon, only a-zA-Z0-9)
  • the word naughty followed directly by a colon and an non-negative integer representing the amount of times Santa caught you being naughty
  • the word nice followed directly by a colon and an non-negative integer representing the amount of times Santa caught you being nice

All separated with a single whitespace (ASCII 32) between each of them.

Additionally, the name will have no whitespace between the parts of the name Santa Claus -> SantaClaus.

Bonus:

  • (25%): He is Santa Claus, so he needs to check the list twice, and make sure there are no duplicates. (In which case, it just gets the first scores that user has)

Example:

Quill naughty:4 nice:0
naughty:0 Doorknob nice:3
naughty:2 Quill nice:6
nice:3 balpha naughty:3
pops nice:4 naughty:2

Output:

The output should consist of:

The name of the person followed by:

  • If there's more points in naughty, then coal:
  • If there's more points in nice, then toys.
  • But if naughty and nice are equal, then needs more data

    Example output:

  • With organisation bonus and duplicate removal bonus:

Quill coal
Doorknob toys
balpha needs more data
pops toys
  • Without bonus:

Quill coal
Doorknob toys
Quill toys
balpha needs more data
pops toys

Lowest byte count wins!

Quill

Posted 2015-12-17T23:13:24.423

Reputation: 576

4

There's also a typo in the test cases. You misspelled our glorious mod DorkNoob's name :^)

– FryAmTheEggman – 2015-12-17T23:37:06.977

9@FryAmTheEggman ಠ_ಠ – Doorknob – 2015-12-18T00:04:45.510

Can we assume nobody's name is naughty or nice? – PurkkaKoodari – 2015-12-18T01:45:47.860

2Nope, naughty or nice are valid names – Quill – 2015-12-18T01:56:40.720

Does the output have to be space-separated, or can it be in a list? – Maltysen – 2015-12-18T02:15:34.467

Space separated – Quill – 2015-12-18T02:16:04.037

Just curious: why did you choose to eliminate duplicates instead of adding their totals? Too complex? – 2012rcampion – 2015-12-18T02:45:42.403

1That's a good idea... I guess there's always next time... – Quill – 2015-12-18T02:49:47.020

1"balpha needs more data" That sounds about right. – Adam Davis – 2015-12-18T15:23:42.190

Answers

4

Pyth, 68 bytes - 25% = 51

V.zI-hA.g}\:kcNdY=+YGjd+G@c"needs more data
coal
toys"b._-Fmsecd\:SH

Try it online: Demonstration

Jakube

Posted 2015-12-17T23:13:24.423

Reputation: 21 462

5

Julia, 176 169 bytes

s->for l=split(s,"\n") M(r)=parse(matchall(r,l)[1]);g=M(r"e:\K\d+");b=M(r"y:\K\d+");println(replace(l,r" *\w+:\d+ *","")," ",g>b?"toys":b>g?"coal":"needs more data")end

This is an anonymous function that accepts a string and prints the result to STDOUT. To call it, give it a name, e.g. f=s->....

Ungolfed:

function santa(s::AbstractString)
    # Split the input on newlines and process each line separately
    for l in split(s, "\n")
        # Define a function to get the number from the result of a
        # regular expression match
        M(r) = parse(matchall(r, l)[1])

        # Goodness
        g = M(r"e:\K\d+")

        # Badness
        b = M(r"y:\K\d+")

        # Get the name by replacing the naughty and nice specifications
        # with empty strings and print the line to STDOUT
        println(replace(l, r" *\w+:\d+ *", ""), " ",
                g > b ? "toys" : b > g ? "coal" : "needs more data")
    end
end

Alex A.

Posted 2015-12-17T23:13:24.423

Reputation: 23 761

4

Pyth - 64 bytes

Will try to use packed strings.

jmj\ +hK.g@k\:cd\ @c"needs more data
coal
toys"b._-Fmseck\:SeK.z

Try it online here.

Maltysen

Posted 2015-12-17T23:13:24.423

Reputation: 25 023

This language is sufficiently advanced technology. – Robert Grant – 2015-12-19T12:19:16.133

3

Perl, 138 113 105 103 102 96 - 25% = 72

includes +1 for -p

s/ *\w*(.):(\d+) */$$1=$2,()/eg;$$_++?$_='':s/\n/$".('needs more data',toys,coal)[$e<=>$y].$&/e

Less golfed:

s/ *\w*(.):(\d+) */$$1=$2,()/eg;    # strip naughty/nice, set $a to naughty, $i to nice
                                    # $_ is now the input name followed by \n
$$_++ ? $_='' :                     # only output once per name
s/\n/                               # replace newlines with:
  $".                               # a space,
  ('needs more data',toys,coal)     # one of these strings,
  [$e<=>$y]                         # indexed by -1, 0 or 1
  .$&                               # and the matched newline.
/ex                                 # (/x only for legibility)

  • update 113
    • save 25 bytes by using 1 letter from nice or naughty as variable name;
    • loose 5 bytes by fixing bug when name is last
  • update 105 save 8 bytes by using <=> to index a list of output strings.
  • update 103 save 2 bytes by using regex to append output string
  • update 102 save 1 byte by using last letter of nice or naughty instead of 2nd.
  • update 96 save 6 bytes by changing $$_ ? ... : ($$_++, ...) into $$_++ ? ... : ...
    (why didn't I see that before).

Kenney

Posted 2015-12-17T23:13:24.423

Reputation: 946

3

Ruby, 144 123 155 * .75 = 116.25 bytes

->s{d={}
s.split("
").map{|l|
a=l.split
b=a.grep /:/
i,j,v=(b.sort*'').scan(/\d+/)+a-b
d[v]||(d[v]=0
puts v+' '+['needs more data','coal','toys'][i<=>j])}}

Thanks to histocrat for suggesting grep method.

164 * .75 = 123 bytes

->s{d={}
s.split("
").map{|l|
a=l.split
b=a.select{|t|t[?:]}
i,j,v=(b.sort*'').scan(/\d+/)+a-b
d[v]||(d[v]=0
puts v+' '+['needs more data','coal','toys'][i<=>j])}}

144 bytes

->s{puts s.split("
").map{|l|b=(a=l.split).select{|t|t[?:]};i,j=(b.sort*'').scan(/\d+/);(a-b)[0]+' '+['needs more data','coal','toys'][i<=>j]}}

Ungolfed

->s{
  d={}
  s.split("
  ").map{ |l|
    a = l.split
    b = a.grep /:/
    i, j, v = (b.sort * '').scan(/\d+/) + a-b
    d[v] ||
      (d[v]=0
       puts v + ' ' + ['needs more data','coal','toys'][i<=>j]
      )
  }
}

Usage:

# Assign the anonymous function to a variable
f = ->s{d={}
s.split("
").map{|l|
a=l.split
b=a.grep /:/
i,j,v=(b.sort*'').scan(/\d+/)+a-b
d[v]||(d[v]=0
puts v+' '+['needs more data','coal','toys'][i<=>j])}}

f["Quill naughty:4 nice:0
naughty:0 Doorknob nice:3
naughty:2 Quill nice:6
nice:3 balpha naughty:3
pops nice:4 naughty:2"]

Quill coal
Doorknob toys
balpha needs more data
pops toys

Vasu Adari

Posted 2015-12-17T23:13:24.423

Reputation: 941

.select{|t|t[?:]} can be golfed to .grep(/:/) – histocrat – 2015-12-19T19:18:18.460

@histocrat Wow i totally forgot that method. Thank you :) – Vasu Adari – 2015-12-19T19:46:02.163

2

JavaScript (ES6), 174 bytes - 25% bonus = 130.5 score

s=>s.split`
`.map(l=>l.split` `.map(p=>(m=p.match(/\w:\d+/))?(n=+m[0].slice(2),m>"f")?b=n:c=n:a=p)&&d[a]?"":d[a]=a+" "+(b>c?`coal
`:b<c?`toys
`:`needs more data
`),d={}).join``

Explanation

s=>
  s.split`
`.map(l=>                   // for each line l of Santa's list
    l.split` `.map(p=>      // for each word p in l
      (m=p.match(/\w:\d+/)) // m = "y:x" for naughty, "e:x" for nice or null for name
        ?(n=+m[0].slice(2), // n = number at end of match
          m>"f")?b=n:c=n    // if naughty matched b = n, if nice matched c = n
        :a=p                // if no match, a = name
    )
    &&d[a]?"":              // if the name has been used before, add nothing to output
    d[a]=                   // else set d[name] to true

      // Add the appropriate text to the output
      a+" "+(b>c?`coal
`:b<c?`toys
`:`needs more data
`),

    // NOTE: This line is executed BEFORE the code above it in the map function...
    d={}                    // d = list of names that have been output
  )
  .join``                   // return the list of outputs as a string

Test

var solution = s=>s.split`
`.map(l=>l.split` `.map(p=>(m=p.match(/\w:\d+/))?(n=+m[0].slice(2),m>"f")?b=n:c=n:a=p)&&d[a]?"":d[a]=a+" "+(b>c?`coal
`:b<c?`toys
`:`needs more data
`),d={}).join``
<textarea rows="5" cols="40" id="input">Quill naughty:4 nice:0
naughty:0 Doorknob nice:3
naughty:2 Quill nice:6
nice:3 balpha naughty:3
pops nice:4 naughty:2</textarea><br />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

user81655

Posted 2015-12-17T23:13:24.423

Reputation: 10 181

2

CJam, 64 bytes

qN/{S/':f/_{,1=},_@^$1f=:~:-g"needs more data
coal
toys"N/=S\N}/

Try it online!

Dennis

Posted 2015-12-17T23:13:24.423

Reputation: 196 637

2

Lua, 329 Bytes - 25% bonus = 246.75

a={...}p={}u=" "k=ipairs for i=1,#a/3 do p[i]={}end for i,v in k(a)do p[math.floor((i+2)/3)][(v:find("y:")and 3)or(v:find("e:")and 2)or 1]=v:gsub("%a+%:","")end for i,v in k(p)do d=tonumber b,g,n=d(v[3]),d(v[2]),v[1]if(not u:find(" "..n.." "))then u=u..n.." "print(n..(g<b and" coal"or g>b and" toys"or" needs more data"))end end

Will edit in ungolfed version and explanations later, a bit tired at the moment. All input is taken in through command line, space separated.

Cyv

Posted 2015-12-17T23:13:24.423

Reputation: 211

2

Python 2, 206 bytes - 25% = 154.5

s=[]
x=[0,0]
for p in zip(*(iter(input().split()),)*3):
 for w in p:
  j=w.find(':')+1
  if j:x[j<6]=int(w[j:])
  else:N=w
 b,g=x
 if N not in s:print N,['needs more data','coal','toys'][(b>g)-(g>b)];s+=[N]

TFeld

Posted 2015-12-17T23:13:24.423

Reputation: 19 246

2

JavaScript (ES6) 120 (160-25%)

Anonymous function using template strings, there are 4 newlines that are significant and included in the byte count

l=>l.split`
`.map(r=>k[r=r.replace(/\S+:(\d+)/g,(a,c)=>(t-=a[1]<'i'?c:-c,''),t=0).trim()]?'':k[r]=r+(t>0?` toys
`:t<0?` coal
`:` needs more data
`),k={}).join``

edc65

Posted 2015-12-17T23:13:24.423

Reputation: 31 086