10
\$\begingroup\$

After all assignments are submitted, a dictionary is created that maps student number to the hash of their file.

This dictionary, or hashmap, or mapping (whatever your language calls it) will look as follows:

{100: "aabb", 104: "43a", 52: "00ab", 430: "aabb", 332: "43a"}

The key is the student number, and the value is the hash.

Our task is to pick out the cheaters! The cheaters are the ones which have identical hashes.

Given the input {100: "aabb", 104: "43a", 52: "00ab", 430: "aabb", 332: "43a"}, the function should return (or print) the following text:

100 has identical files to 430

104 has identical files to 332

Notice how the files where the hashes are unique are not mentioned.

Also, the order is important here:

{100: "aabb", 202: "aabb", 303: "ab", 404: "aabb"} should return (print) the following text:

100 has identical files to 202,404

It is incorrect to print any of the following:

202 has identical files to 100,404

100 has identical files to 404, 202

You should print it in terms of how it appears in the dictionary. In some languages, going through a dictionary is random, so in this special case, you are allowed to change the method of input such that you can go through it in an orderly fashion.

More Examples:

{} # prints nothing

{100: "ab", 303: "cd"} # prints nothing again

{100: "ab", 303: "cd", 404: "ab"}

100 has identical files to 404

{303: "abc", 304: "dd", 305: "abc", 405: "dd", 606: "abc"}

303 has identical files to 305,606

304 has identical files to 405

Shortest code wins!

\$\endgroup\$
10
  • \$\begingroup\$ "You should print it in terms of how it appears in the dictionary" -- I'm not entirely sure what this means. Otherwise I do like the challenge. \$\endgroup\$
    – Giuseppe
    Dec 6, 2018 at 22:52
  • 3
    \$\begingroup\$ Might I also suggest using the sandbox before posting to the main site? always helpful to get revisions to a question before posting instead of getting a million comments for clarification on main :-) \$\endgroup\$
    – Giuseppe
    Dec 6, 2018 at 22:55
  • 1
    \$\begingroup\$ In the case where multiple groups of cheaters are found, is there a required order between groups? For example, in the last test case can "304 has..." be printed before "303 has..."? \$\endgroup\$ Dec 7, 2018 at 1:46
  • 2
    \$\begingroup\$ Are we allowed to output 303 has identical files to [305, 606] instead of 303 has identical files to 305,606? \$\endgroup\$ Dec 7, 2018 at 9:35
  • 1
    \$\begingroup\$ In languages where a dictionary, map, or hashmap type does not exist, are lists of tuples (or equivalent) allowed? \$\endgroup\$
    – user77406
    Dec 10, 2018 at 20:19

11 Answers 11

2
\$\begingroup\$

JavaScript (Babel Node), 113 bytes

Takes input as an array of arrays in [key, value] format. Go go gadget double flatMap!

o=>o.flatMap(([x,h],i)=>(a=o.flatMap(([y,H],j)=>j>i&H==h?(o[j]=[,j],[y]):[]))+a?x+' has identical files to '+a:a)

Try it online!


JavaScript (Babel Node), 114 bytes

Takes input as a native JS object.

o=>Object.keys(o).flatMap((x,i,a)=>(a=a.filter(y=>i--<0&o[y]==o[x]&&(o[y]=y)))+a?x+' has identical files to '+a:a)

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Really nice! Quite a large file but then again I did not expect this problem to be as easy as the other ones. Great work! I'll look more into this flatMap \$\endgroup\$
    – K Split X
    Dec 7, 2018 at 0:22
  • \$\begingroup\$ @KSplitX flatMap is not widely supported yet. I'm sure there are shorter ways, but it's getting late and I can't think anymore. :p \$\endgroup\$
    – Arnauld
    Dec 7, 2018 at 0:35
2
\$\begingroup\$

Python 2, 127 126 bytes

def f(x):
 for l in{`[K for K,V in x if v==V]`[1:-1]for k,v in x}:
	if','in l:print l.replace(',',' has identical files to',1)

Try it online!

Takes a list of ordered pairs (<studentNumber>,<hash>) as input.

\$\endgroup\$
2
  • \$\begingroup\$ Missed a small golf: if','in \$\endgroup\$ Dec 7, 2018 at 7:58
  • \$\begingroup\$ @Vedant Kandoi: Thx! \$\endgroup\$
    – Chas Brown
    Dec 7, 2018 at 21:14
1
\$\begingroup\$

Retina 0.8.2, 71 bytes

+m`((:.+)$(¶|.)+?)^(.+)\2$
,$4$1
:.*

G`,
%1`,
 has identical files to 

Try it online! Takes input on separate lines but link includes test suite that splits the examples for you. Explanation:

+

Repeat this match until no more replacements can be made.

m`((:.+)$(¶|.)+?)^(.+)\2$
,$4$1

Look for pairs of matching hashes and append the key of the second match to that of the first match with a comma separator.

:.*

Delete all of the hashes.

G`,

Keep only the lines with commas.

%1`,
 has identical files to 

Replace the first comma on each line with the desired text (including trailing space).

\$\endgroup\$
1
\$\begingroup\$

R, 145 132 129 126 124 bytes

function(m,`!`=names)for(e in !(t=table(m))[t>1])cat(el(n<-!m[m==e]),'has identical files to',paste(n[-1],collapse=','),'
')

Try it online!

It takes a named vector as input (names are the keys)

  • -2 bytes thanks to Giuseppe

If ", " separator (with a space after the comma) is allowed in case of multiple duplicates, we can use this code and save 10 bytes :

R, 114 bytes

function(m,`!`=names)for(e in !(t=table(m))[t>1])cat(el(n<-!m[m==e]),'has identical files to',toString(n[-1]),'
')

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ 124 bytes although my gut tells me a different approach might yield something in the 115 range... \$\endgroup\$
    – Giuseppe
    Dec 7, 2018 at 21:22
0
\$\begingroup\$

05AB1E, 34 bytes

Σθ}.γθ}vyg1›iy€нć“ÿ€°Ê¼‡œ€„ “?',ý,

Try it online or verify all test cases.

Explanation:

Σθ}                   # Sort the (implicit) input by the string
.γθ}                  # Then group it by the string
v                     # Loop `y` over each grouped inner list
 yg1›i                #  If the group contains more than 1 key-value pairs:
      y€н             #   Only leave the keys
      ć               #   Pop and push the head and rest of the list separately
                      #   (with the head being at the top of the stack now)
       “ÿ€°Ê¼‡œ€„ “   #   Compressed string "ÿ has identical files to "
                      #   where the "ÿ" is automatically replaced with the top of the stack
                   ?  #   Print it (without trailing newline)
       ',ý           '#   Join the remaining numbers by a comma
          ,           #   And output it as well (with trailing newline)

See this 05AB1E answer of mine (section How to use the dictionary?) to understand why “ÿ€°Ê¼‡œ€„ “ is "ÿ has identical files to ".

\$\endgroup\$
0
\$\begingroup\$

Ruby, 98 96 bytes

->h{h.group_by{|k,v|v}.map{|k,v|x,*y=v.to_h.keys;p"#{x} has identical files to #{y*?,}"if y[0]}}

Try it online!

Takes input as Ruby Hash, returns by printing.

\$\endgroup\$
0
\$\begingroup\$

Jelly, 39 bytes

Ṫ€ĠḊƇṢịẎµḢ;“]⁶ḅhṬyU⁹æṇL[Oþ⁹cƘƓ»,ṾK)j⁾¶¶

Try it online!

\$\endgroup\$
0
\$\begingroup\$

C# (Visual C# Interactive Compiler), 130 bytes

a=>a.GroupBy(x=>x.Value,x=>x.Key).Where(x=>x.Count()>1).Select(x=>x.First()+" has identical files to "+String.Join(",",x.Skip(1)))

Try it online!

The strange thing about this question is that the examples are given in a JSON format as key/value pairs which usually implies that they are unordered... In this case however, order is important. As such, I am using a list of tuples for input and a list of strings as output.

// a is a list of tuples
// (student #, hash)
a=>a
  // group by hash
  // grouped items are the student #'s
  .GroupBy(x=>x.Value,x=>x.Key)
  // remove single student groups
  .Where(x=>x.Count()>1)
  // format the output strings
  .Select(x=>x.First()+
    " has identical files to "+
    String.Join(",",x.Skip(1)))
\$\endgroup\$
0
\$\begingroup\$

Perl 5, 100 +1(-n) bytes

for$x(/[a-z]+/g){($t,@a)=${h{$x}}++?():/\d+(?= $x)/g;@a&&say"$t has identical files to ",join",",@a}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Japt, 34 bytes

üÌl>1 ®mgîÎ+` •s ÅÁÈól fÅC ‘ `+ZÅ

Try it online!

Right now it's a bit inconsistent in the ordering of lines, but within a line it outputs correctly. If the lines of the output need to be in a specific order, it will take a few more bytes. Input is just an array of [id, hash] pairs

Explanation:

üÌ                                    :Group by hash
  l>1                                 :Remove the ones that are unique
      ®mgà                            :Get just the Ids
          ®                           :Generate a string for each hash:
           Î                          : The first Id with that hash
            +` •s ÅÁÈól fÅC ‘ `       : Plus " has identical files to " compressed
                               +ZÅ    : Plus the remaining Ids
                                      : Implicitly comma delimited
\$\endgroup\$
0
\$\begingroup\$

Perl 6, 115 110 103 bytes

-2 bytes thanks to Jo King

{unique map {.[0]~" has identical files to "~join ',',.skip},grep *>1,.map:{.grep(*{*}eq$^p{*})>>.key}}

Try it online!

Takes a list of Pairs since hashes are unordered. A list of two-element lists would save a few bytes but seems unidiomatic. Returns a list of lines.

95 88 bytes if the order of lines in the result doesn't matter:

*.classify(*{*}){*}>>.key.grep(*>1).map:{.[0]~" has identical files to "~join ',',.skip}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ .[1..*] to .skip \$\endgroup\$
    – Jo King
    Dec 8, 2018 at 1:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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