Write a Chat Ping Counter

19

3

Your task is to write a program, that given a list of chat messages, count how many times each person gets pinged, so I can know how popular everyone is. But, since I have to do it surreptitiously, I need it to be as small as possible so I can hide the code.

Specs

  • The input comes in a list of 2-tuples, with each item being of the form ("username", "message").
  • A ping to another user is defined as an @ followed by 3 or more letters that unambiguously refers to that user.
  • However, you also have to consider replies, which have to start with :messageid followed by a space.
  • Assume the first message has id 0 and proceed sequentially.
  • Output each user and say how many times each one got pinged.
  • The output can be in any order/reasonable format.
  • This is , so shortest code in bytes wins!

Test Cases

[["AlexA.", "I am wrong"], ["Quartatoes", "@Alex you are very wrong"], ["AlexA.", ":1 I am only slightly wrong"]]
AlexA.: 1
Quartatoes: 1

[["Doorknob", "I have never eaten an avocad."], ["AquaTart", ":0 I will ship you an avocad"], ["AlexA.", ":0 this is shocking"]]
Doorknob: 2
AquaTart: 0
AlexA.: 0

[["Geobits", "I like causing sadness through downvotes."], ["Flawr", "I want to put random message ids in my chat messages :0 askjdaskdj"]]
Geobits: 0
Flawr: 0

[["Downgoat", "goatigfs.com/goatgif"], ["Downotherthing", "@Downgoat cool gifs"], ["Dennis", "@Down cool gifs this is an ambiguous ping"]]
Downgoat: 1
Downotherthing: 0
Dennis: 0

Maltysen

Posted 2016-02-29T14:07:04.620

Reputation: 25 023

2I like how :0 doubles as a surprised emoticon. – Doorknob – 2016-02-29T14:08:27.077

4"I like causing sadness through downvotes." You know there's only one proper way I can respond to that, right? ;) – Geobits – 2016-02-29T14:15:54.143

Can there be multiple pings in each message? If so, can they be of different "types" (reply and one or more pings)? And if so, could you add some test cases involving this? – Doorknob – 2016-02-29T14:17:17.607

@Doorknob yes to all of these questions, I will add cases. – Maltysen – 2016-02-29T14:19:51.980

@Maltysen Can the username contain spaces? And would username message\nusername message be a valid way to take input? – andlrc – 2016-02-29T14:45:58.473

9At what point are we stopping with the "Alex is wrong" jokes? – Martin Ender – 2016-02-29T15:36:31.930

Can replies contain mentions e.g. :0 @someone? – vaultah – 2016-02-29T16:18:21.453

Can I take the input as an array of objects, such as [{user: "name", msg: "words"}, {...}]? – Mwr247 – 2016-02-29T16:25:55.330

1Can a reply be out of range (e.g. first message starting with :3) or a ping not satisfying any user in the room (e.g. @zzz)? – Sp3000 – 2016-02-29T16:33:49.490

The final example seems invalid - @Down does not unambiguously refer to any user. – isaacg – 2016-02-29T17:34:31.170

@isaacg That's the idea. Per the 2nd spec, they should only count towards a user if it referes to them unambiguously. Because @Down could refer to two people, it should be ignored. – Mwr247 – 2016-02-29T17:38:00.013

@Mwr247 I get it - I thought that that spec meant that such ambiguous pings couldn't appear in the input, by rereading things I see that you're right. – isaacg – 2016-02-29T17:39:11.833

2Can a pinged user not yet have posted a message when he's pinged? e.g. is [["Doorknob","@Alex is wrong"],["Alex","I am only slightly wrong"]] valid input? – ETHproductions – 2016-03-01T01:19:10.727

Answers

2

JavaScript (ES6), 245 210 bytes

a=>(p={},a.map(b=>p[b[0]]=0),(a.map(b=>b[1].match(/@[a-z]{3,}|^:\d+/gi)||[]).map(c=>c.map(d=>(z=(d[0]=='@'?(y=Object.keys(p).filter(e=>e.startsWith(d.slice(1)))).length<2?y:0:a[d.slice(1)[0]]))&&p[z[0]]++))),p)

Uses an object to create a unique list of names alongside pings. Then it looks through the messages for matches to either ping condition. If a name, it looks through the list of names to find if there is only one match, and then increments. If a reply, it simply references that index in the message array and pulls the name to be incremented. Finally, it returns the object.

Mwr247

Posted 2016-02-29T14:07:04.620

Reputation: 3 494

Surely using an object is shorter. If it isn't I don't think you need to return the Map as an array – Downgoat – 2016-02-29T22:56:52.427

@Downgoat But Map is more fun right? Na, I originally overestimated how much extra it would take to reference an object, thinking I would have to a separate array for names, but you're right that it is much shorter this way. – Mwr247 – 2016-03-01T00:44:49.537

0

PHP, 227 Bytes

foreach($_GET[a]as $c){$r[]=&$n[$c[0]]??$n[$c[0]]=0;preg_match("#^(:(\d+)|@(\w+))#",$c[1],$m);$m[2]==""?!$m[3]?:count($a=preg_grep("#^{$m[3]}#",array_keys($n)))>1?:$n[end($a)]++:$r[$m[2]]++;}foreach(($n)as$k=>$v)echo"$k: $v\n";

Jörg Hülsermann

Posted 2016-02-29T14:07:04.620

Reputation: 13 026