# Help me pair my socks

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.

# 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: []

# 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
}


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.

• 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)
– Jo King
Nov 27, 2019 at 10:44
• @JoKing: For me it's not outputting 0 on my computer. Strange. Nov 27, 2019 at 10:45
• I will edit my answer for your suggestions. Nov 27, 2019 at 10:47
• Ah, it seems you don't need the surrounding quotes in the argument, otherwise it tries to parse "1 as an integer
– Jo King
Nov 27, 2019 at 10:49