29
\$\begingroup\$

Disclaimer: This challenge inspired by me trying to find pairs in a large pile of socks.

Disclaimer: This is looking for a very different process and output to Help me sort my socks!. Please don't claim it as a duplicate until you've read both ;)


So, I have a huge pile of socks. Of course I keep them categorized by compatibility number. Compatible socks, which I can wear together, have the same number. (Of course, every programmer does this).

My super-convenient plot device quickly scans the pile and outputs an array of compatibility numbers for the pile. It looks a bit like this:

[2, 3, 3, 6, 0, 4, 9, 1, 6, 7, 11, 3, 13, 3, 
5, 12, 2, 1, 10, 2, 1, 11, 2, 13, 12, 10, 1, 
7, 0, 0, 12, 12, 6, 2, 13, 6, 10, 0, 0, 12, 
5, 0, 2, 3, 4, 0, 5, 8, 1, 6, 9, 7, 10, 14, 
10, 8, 3, 8, 9, 8, 5, 11, 7, 9, 9, 9, 7, 14, 
4, 2, 8, 14, 3, 11, 12, 14, 7, 13, 11, 13, 4, 
7, 5, 12, 3, 1, 12, 4, 5, 13, 2, 13, 2, 14, 1, 
13, 11, 1, 4, 8]

That's good data, but it's about as much use to me as scanning the pile myself by eye. What I want to know is how many compatible pairs I need to look for, and which are going to be 'odds', which I can discard for now.

In the above example, I am looking for these pairs of socks:

{3=>4, 6=>2, 2=>4, 1=>4, 11=>3, 13=>4, 12=>4, 10=>2, 7=>3, 0=>3, 5=>3, 4=>3, 9=>3, 8=>3, 14=>2}

(4 pairs of number 3, 2 pairs of number 6 etc.)

And these numbers will have 'odd ones out'. When I've found all the pairs for these, I can discard the last one.

[0, 6, 10, 7, 2, 14] 

The challenge

  • Convert a list of compatible numbers to a count of pairs for each number and an array of 'odds'.
    • The pairs will be composed of a data structure (hash, or other) showing how many pairs can be made of each compatibility number (can be skipped if no pairs can be made).
    • The odds will be composed of a list of numbers which occur and odd number of times in the array.
  • The order of the outputs is not significant.
  • The size of my sock pile can, of course, be arbitrarily large.

The Rules

  • It's golf, make it short.
  • No standard loopholes.
  • Use any language you like.
  • Please include a link to an online interpreter.

Test Cases

Input: [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]

Output:

Pairs: {2=>1, 3=>1, 4=>2, 5=>2}

Odds: [1, 3, 5]


Input: [2, 3, 3, 6, 0, 4, 9, 1, 6, 7, 11, 3, 13, 3, 5, 12, 2, 1, 10, 2, 1, 11, 2, 13, 12, 10, 1, 7, 0, 0, 12, 12, 6, 2, 13, 6, 10, 0, 0, 12, 5, 0, 2, 3, 4, 0, 5, 8, 1, 6, 9, 7, 10, 14, 10, 8, 3, 8, 9, 8, 5, 11, 7, 9, 9, 9, 7, 14, 4, 2, 8, 14, 3, 11, 12, 14, 7, 13, 11, 13, 4, 7, 5, 12, 3, 1, 12, 4, 5, 13, 2, 13, 2, 14, 1, 13, 11, 1, 4, 8]

Output:

Pairs: {3=>4, 6=>2, 2=>4, 1=>4, 11=>3, 13=>4, 12=>4, 10=>2, 7=>3, 0=>3, 5=>3, 4=>3, 9=>3, 8=>3, 14=>2}

Odds: [0, 6, 10, 7, 2, 14]


Input: [1, 2, 1, 2]

Output:

Pairs: {1=>1, 2=>1}

Odds: []


Input: [1,2,3]

Output:

Pairs {}

Odds: [1,2,3]


Input: []

Output:

Pairs: {}

Odds: []

\$\endgroup\$
0

32 Answers 32

1
2
1
\$\begingroup\$

Burlesque, 27 bytes

raf:Jf{-]2.%})[-jm{g_2./_+}

Try it online!

ra   #Read input as array
f:   #Calculate frequency list
J    #Duplicate
f{   #Filter for
 -]  #Frequency
 2.% #Mod 2 != 0
}
)[-  #Get odd IDs
j    #Swap
m{   #For each block of the frequency list
 g_  #Pop count
 2./ #Divide by 2
 _+  #Concatenate back on
}
\$\endgroup\$
0
\$\begingroup\$

As suggested by JoKing this can be substantially shortend to:

Ruby, 90 bytes

c=Hash.new(0)
ARGV.each{|s|c[s.to_i]+=1}
c.each{|k,v|p k if(p"#{k}=>#{v/2}"if v>1)&&v%2>0}

Try it online!

Old version:

Ruby, 139 bytes

c=Hash.new(0)
ARGV[0].split(",").map(&:to_i).each{|s|c[s]+=1}
o = []
c.each{|k,v|o<<k if v.odd?}
c.each{|k,v|o<<"#{k}=>#{v/2}" if v!=1}
p o

Try it online!

Pardon me for writing non-idiomatic Ruby maybe.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ I don't really know Ruby, but you could do something like this for 116 bytes, right? Or even 90 bytes (err, I also notice that there's an extra 0 in the odds section) \$\endgroup\$
    – Jo King
    Nov 27, 2019 at 10:44
  • \$\begingroup\$ @JoKing: For me it's not outputting 0 on my computer. Strange. \$\endgroup\$
    – stephanmg
    Nov 27, 2019 at 10:45
  • \$\begingroup\$ I will edit my answer for your suggestions. \$\endgroup\$
    – stephanmg
    Nov 27, 2019 at 10:47
  • 1
    \$\begingroup\$ Ah, it seems you don't need the surrounding quotes in the argument, otherwise it tries to parse "1 as an integer \$\endgroup\$
    – Jo King
    Nov 27, 2019 at 10:49
1
2

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.