20
\$\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\$
  • 3
    \$\begingroup\$ Is it OK to report 0 pair? (e.g. {1=>0, 2=>0, 3=>0} for the penultimate test case) \$\endgroup\$ – Arnauld Nov 21 at 13:52
  • 4
    \$\begingroup\$ I think you should either remove this constraint or make it more explicit. Two out of 3 answers are already breaking this rule. \$\endgroup\$ – Arnauld Nov 21 at 14:03
  • 4
    \$\begingroup\$ @Arnauld Fine, I've edited it to make this optional. \$\endgroup\$ – AJFaraday Nov 21 at 14:04
  • 2
    \$\begingroup\$ @KevinCruijssen Okay, it definitely can have gaps, and I wouldn't like to see output for numbers which aren't represented in the input. \$\endgroup\$ – AJFaraday Nov 21 at 16:16
  • 3
    \$\begingroup\$ @KevinCruijssen After all, sometimes you've just got to throw out that trusty number 19 sock. \$\endgroup\$ – AJFaraday Nov 21 at 16:20

30 Answers 30

7
\$\begingroup\$

Python 3.8, 85 78 73 72 bytes

lambda s:{*((c,(d:=s.count)(c)//2)for c in s),*(c for c in s if d(c)%2)}

Try it online!


Output is a list where pairs are tuples, (a, b) rather than a => b, and odds are not part of a tuple.

There's a sub-70 in here somewhere just staring at me, I can feel it...

Previous Version (73 bytes):

lambda s:{*((c,s.count(c)//2)for c in s),*(c for c in s if s.count(c)%2)}
\$\endgroup\$
  • 2
    \$\begingroup\$ If you change the outer parens to brackets, you can replace ,* with +: Try it online! \$\endgroup\$ – isaacg Nov 22 at 5:47
6
\$\begingroup\$

Perl 6, 46 bytes

{.kv.map(*=>*+>1),.keys.grep:{.{$^k}%2}}o*.Bag

Try it online!

Explanation

{                                      }o*.Bag  # Convert to Bag and feed into block
                 ,  # 2-element list
 .kv  # Key-value list (key is sock type, value is count)
    .map(       )  # Map to
         *=>*+>1   # Pair of sock type and count right-shifted by 1
                  .keys  # Keys (sock types)
                       .grep:  # Filter
                             {.{$^k}%2}  # Count is odd
\$\endgroup\$
6
\$\begingroup\$

05AB1E, 23 21 bytes

{γεÙygª}Dε`2÷‚}sø`ÉÏ‚

Outputs as a pair of lists, where both are ordered ascending by key. Also includes the optional value=0 pairs in the output, like all answers.

(Initially) inspired by @Malivil's C# answer, so make sure to upvote him as well!

Try it online or verify all test cases.

Explanation:

{           # Sort the (implicit) input-list
            #  i.e. [4,2,3,3,1,3,2,4,4,3,4,3] → [1,2,2,3,3,3,3,3,4,4,4,4]
 γ          # Split it into groups of the same keys
            #  i.e. [1,2,2,3,3,3,3,3,4,4,4,4] → [[1],[2,2],[3,3,3,3,3],[4,4,4,4]]
            # (this is shorter than the regular (unsorted) group-by `.¡}`)
  ε         # Map each inner list `y` to:
   Ù        #  Uniquify the list, so a single key wrapped in a list remains
            #   i.e. [3,3,3,3,3] → [3]
    yg      #  Push the list `y` again, and pop and push its length (the count)
            #   i.e. [3,3,3,3,3] → 5
      ª     #  Append it to the 'key-list' to create the key-count pair
            #   i.e. [3] and 5 → [3,5]
            #  i.e. [[1],[2,2],[3,3,3,3,3],[4,4,4,4]] → [[1,1],[2,2],[3,5],[4,4]]
  }D        # After the map: duplicate the list of key-count pairs
    ε       # Map it to:
     `      #  Push key and count separated to the stack
            #   i.e. [3,5] → 3 and 5
      2÷    #  Integer-divide the count by 2
            #   i.e. 5 → 2
        ‚   #  And pair them back together
            #   i.e. 3 and 2 → [3,2]
            #  i.e. [[1,1],[2,2],[3,5],[4,4]] → [[1,0],[2,1],[3,2],[4,2]]
    }s      # After this map: swap to get the initial duplicated key-count pairs again
      ø     # Zip/transpose; swapping rows/columns
            #  i.e. [[1,1],[2,2],[3,5],[4,4]] → [[1,2,3,4],[1,2,5,4]]
       `    # Push both lists separated to the stack
        É   # Check for each count whether it is odd
            #  i.e. [1,2,5,4] → [1,0,1,0]
         Ï  # Only leave the keys at the truthy indices
            #  i.e. [1,2,3,4] and [1,0,1,0] → [1,3]
          ‚ # And pair it together with the earlier created list of key-count//2 pairs
            # (after which the result is output implicitly)
\$\endgroup\$
6
\$\begingroup\$

Python 2, 68 bytes

lambda A:({v:A.count(v)/2for v in A},{v for v in A if A.count(v)%2})

Try it online!

Outputs a dict containing the number of pairs, and a set of left-over sock ids.

\$\endgroup\$
6
\$\begingroup\$

05AB1E, 11 bytes

¢2÷øê,¢ÉÏê,

Try it online!

¢              # count occurences of each element in the input
 2÷            # integer divide by 2
   ø           # zip with the input
    ê          # sort and uniquify
     ,         # output (this is the list of pairs counts)
¢              # count occurences of each element in the input
 É             # mod 2
  Ï            # filter the input, keep only where the above is 1
   ê           # sort and uniquify
    ,          # output (this is the list of singles)
\$\endgroup\$
5
\$\begingroup\$

R, 47 bytes

S=table(scan());S[S%/%2>0]%/%2;names(S[!!S%%2])

Try it online!

Returns a table with names equal to the compatibility number and the pair counts as the values, as well as the compatibility numbers (as strings) of unpaired socks.

\$\endgroup\$
  • \$\begingroup\$ Would there be a way to turn %/%2 into a single digit? \$\endgroup\$ – Xi'an Nov 23 at 9:15
4
\$\begingroup\$

J, 39 27 26 24 bytes

~.((,.<.@-:);[#~2|])#/.~

Try it online!

-2 bytes thanks to ngn

\$\endgroup\$
  • \$\begingroup\$ ,&< -> ;­­­ \$\endgroup\$ – ngn Nov 23 at 21:24
  • \$\begingroup\$ Ofc, thank you @ngn. \$\endgroup\$ – Jonah Nov 24 at 2:55
4
\$\begingroup\$

APL (Dyalog Unicode), 23 bytesSBCS

Anonymous tacit prefix function. Prints (unique sock number, count of pairs) pairs, then prints list of odds.

∊{⊂(2|≢⍵)/⊃⎕←⍺,⌊2÷⍨≢⍵}⌸

Try it online!

{}⌸ on each (unique sock number, its indices in sock list):

 indices in sock list; [4,5,6]

 count them; 3

2÷⍨ let two divide them; 1.5

 round down; 1

⍺, prepend sock number; [3,1]

⎕← send to console; "3 1\r"

 pick the first (the sock number); 3

()/ make this many copies of that:

  ≢⍵ the count of indices; 3

  2| the 2-mod of that (i.e. "is it odd?"); 1

 enclose so all the results will be self-contained; [1]

ϵnlist (flatten); [1,3,5]

\$\endgroup\$
  • \$\begingroup\$ ⊂(2|≢⍵)/ -> ~/⍵⊢¨ -> ⍵~.⊢ \$\endgroup\$ – ngn Nov 23 at 15:01
  • \$\begingroup\$ the whole thing is shorter as a pair of lines: ,∘(⊢+.<⌽)⌸⎕ newline ∊~.⊣⌸⎕ and i'm not sure if the -s are required. \$\endgroup\$ – ngn Nov 24 at 13:28
  • \$\begingroup\$ .. or maybe needs to be assigned to a variable as it's read twice? at worst it's 20 bytes as a train: ,∘(⊢+.<⌽)⌸{⍺⍵}∘∊~.⊣⌸ \$\endgroup\$ – ngn Nov 24 at 13:31
  • \$\begingroup\$ @ngn Aaand there's nothing left of my original solution. Post it! \$\endgroup\$ – Adám Nov 24 at 16:59
  • \$\begingroup\$ i've just realised the last test fails with a domain error :( \$\endgroup\$ – ngn Nov 24 at 17:04
4
\$\begingroup\$

C# (Visual C# Interactive Compiler), 162 154 136 128 108 bytes

a=>(a.GroupBy(x=>x).Select(x=>(x.Key,x.Count()/2)),a.GroupBy(x=>x).Where(x=>x.Count()%2>0).Select(x=>x.Key))

Try it online!

-8 bytes thanks to @Kevin Cruijssen for pointing out an unnecessary variable

-18 more bytes thanks to @Kevin Cruijssen for letting me know the 0 rule was made optional and changing the return type from dynamic to array

-8 bytes thanks to @my pronoun is monicareinstate for in-lining the grouping assignment which changes this to a true one-liner

-20 bytes thanks to @Innat3 for changing the grouping to remove an un-needed comparison

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice answer, +1 from me. You can golf 8 bytes by not using a variable c, since it can be done directly in the result-tuple as well: 154 bytes. \$\endgroup\$ – Kevin Cruijssen Nov 21 at 14:07
  • \$\begingroup\$ Ah, nice catch. Thanks! \$\endgroup\$ – Malivil Nov 21 at 14:19
  • 1
    \$\begingroup\$ Apparently it's now optional to output with values 0 (since currently all answers except for yours did it incorrect :D). This does mean you can golf your answer as well, by removing the .Where(g=>g.v>0) and changing the new{k=g.Key,v=g.First()/2} to new[]{g.Key,g.First()/2}: 136 bytes. Unfortunately I can't upvote again for being the only one actually following the initial rules of the challenge. ;p \$\endgroup\$ – Kevin Cruijssen Nov 21 at 15:09
  • 1
    \$\begingroup\$ 128 bytes with an awesome trick I've been thinking about for very long but never found an opportunity to use yet: ...=>{var a=expr;return expr2(a);} can sometimes be rewritten to something like ...=>expr2(expr is var a?a:a) (or something similar). You can save a few bytes but output extra garbage at the beginning by moving the is var b expression to an extra item in the resulting tuple. Pastebin link to TIO link: pastebin.com/fEPSK11V . Fun fact: I haven't read the challenge. \$\endgroup\$ – my pronoun is monicareinstate Nov 22 at 13:11
  • 1
    \$\begingroup\$ 108 bytes \$\endgroup\$ – Innat3 Nov 25 at 13:53
3
\$\begingroup\$

JavaScript (ES10),  91  82 bytes

Returns [odds_array, pair_object].

a=>[[...new Set(a)].flatMap(v=>(a.map(x=>n+=v==x,n=0),o[v]=n>>1,n&1?v:[]),o={}),o]

Try it online!

Commented

a => [               // a[] = input array
  [...new Set(a)]    // build the set of distinct values in a[]
                     // and turn it back into an array
  .flatMap(v =>      // for each value v in there:
    ( a.map(x =>     //   count the number n of values in the original array
        n += v == x, //   that are equal to v
        n = 0        //   start with n = 0
      ),             //
      o[v] =         //   set o[v] to
        n >> 1,      //     floor(n / 2)
      n & 1 ? v : [] //   yield v if n is odd, or [] otherwise
    ),               //
    o = {}           //   o = object holding the number of pairs
  ),                 // end of flatMap()
  o                  // append o
]                    //
\$\endgroup\$
3
\$\begingroup\$

Python 3.8 (pre-release), 63 bytes

lambda s:sum([[(c,(d:=s.count(c))//2)]+d%2*[c]for c in{*s}],[])

Try it online!

Outputs a list, with tuples (a, b) indicating pair counts and solitary elements indicating left over socks.

Interestingly, the hash function on integers seems to be the identity function, and so the output is conveniently ordered [(0, count of 0 pairs), 0 if 0 has odd count, (1, count of 1 pairs), 1 if 1 has odd count, ... as long as a contiguous sequence of numbers starting at 0 is used for sock indicators.

\$\endgroup\$
3
\$\begingroup\$

JavaScript (Node.js), 69 bytes

a=>[a.filter(n=>p[n]?0:(a.map(m=>c+=m==n,c=0),p[n]=c>>1,c%2),p={}),p]

Try it online!

a=>[
  a.filter(n=>               // Filter out paired ones, return unpaired (odd) ones
    p[n]?0:                  // If we already paired it, skip
    (
      a.map(m=>c+=m==n,c=0), // Count
      p[n]=c>>1,             // Count / 2 pairs found
      c%2                    // If count % 2 != 0, there is an odd one
    ),
    p={}                     // Initial pairs dictionary
 ),p]
\$\endgroup\$
3
\$\begingroup\$

Pyth, 17 16 bytes

,R//Qd2{Qf%/QT2{

Try it online!

-1 byte thanks to @isaacg

Two separate operations, returns two separate lists. Includes zero-pairs, which I believe is optional? Can fix at the cost of 2 bytes, if not allowed, by prepending e# -> e#,R//Qd2{Qf%/QT2{

How it works

,R//Qd2{Qf%/QT2{
,R//Qd2{Q            -- Returns pairs
 R      {Q            -  Right map to the input cast to a set
,                     - A two element list starting with the element of the set (implicit)
   //Qd2              - ...and ending with the count of that element in the input/2
          f%/QT2{     -- Returns odds
          f     {     - Filter the implicit input cast to a set
            /QT       - By the count of each element of the set in the input
           %   2      - Modulo 2 

                        Both lists print implicitly
\$\endgroup\$
  • 3
    \$\begingroup\$ Glad you're using my language! m,d is equivalent to ,R - R basically just expands to m d, where the ` ` is whatever's left of the R. \$\endgroup\$ – isaacg Nov 22 at 6:22
  • \$\begingroup\$ Thanks for the suggestion, and for making the language @isaacg! I had read the documentation for right/left mapping but didnt fully understand it, makes more sense now \$\endgroup\$ – frank Nov 22 at 18:00
3
\$\begingroup\$

APL(NARS), chars 66, bytes 132

{∨/c←×b←⌊2÷⍨≢¨a←a⊂⍨1+a←⍵[⍋⍵]:(⊂c/b,¨∪¨a),⊂∪⊃∪/a/⍨0≠2∣≢¨a⋄(⊂⍬),∪/a}

test:

  f←{∨/c←×b←⌊2÷⍨≢¨a←a⊂⍨1+a←⍵[⍋⍵]:(⊂c/b,¨∪¨a),⊂∪⊃∪/a/⍨0≠2∣≢¨a⋄(⊂⍬),∪/a}
  ⎕fmt f 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
┌2─────────────────────────────────────┐
│┌4──────────────────────────┐ ┌3─────┐│
││┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│ │ 1 3 5││
│││ 1 2│ │ 1 3│ │ 2 4│ │ 2 5││ └~─────┘│
││└~───┘ └~───┘ └~───┘ └~───┘2         │
│└∊──────────────────────────┘         3
└∊─────────────────────────────────────┘
  ⎕fmt f 1 2 1 2
┌2───────────────────┐
│┌2────────────┐ ┌0─┐│
││┌2───┐ ┌2───┐│ │ 0││
│││ 1 1│ │ 1 2││ └~─┘│
││└~───┘ └~───┘2     │
│└∊────────────┘     3
└∊───────────────────┘
  ⎕fmt f 1 2 3
┌2────────────┐
│┌0─┐ ┌3─────┐│
││ 0│ │ 1 2 3││
│└~─┘ └~─────┘2
└∊────────────┘
  ⎕fmt f ⍬
┌2────────┐
│┌0─┐ ┌0─┐│
││ 0│ │ 0││
│└~─┘ └~─┘2
└∊────────┘

but if it not be "codegolf" i would write for question of readability this 93 bytes code:

c←{+/⍵=⍺}⋄f←{0=≢a←⍵:⍬⍬⋄(⊂{×≢b←({0≠⌊2÷⍨⍵c a}¨b)/b←∪⍵:b,¨{⌊2÷⍨⍵c a}¨b⋄⍬}⍵),⊂∪({0≠2∣⍵c a}¨a)/a}

because ({0≠⌊2÷⍨⍵c a}¨b)/b or exprestion as that has to be idiomatic... g(f¨b)/b traslate the math set {g(x):x∊b∧f(x)}.

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 155 154 bytes

Thanks to ceilingcat for the suggestion.

I use -1 as the sentinel value for the list. First, I count the length of the input list, then I increment a count array at the index pointed into from the input. Lastly, I print the pairs in type:number of pairs format, then any singles remaining.

I initialize c to zero even though it's a global because it won't necessarily be zero at the end of the function and I need to have it set correctly at the start of the function. I also use a dynamically-allocated count array so that it will be zero-initialized.

d,c,*a;f(int*i){for(c=0;~i[c++];);for(a=calloc(d=c,4);d--;a[i[d]]++);for(d=c;d--;)a[d]&&printf("%d:%d\t",d,a[d]/2);for(d=c;d--;)a[d]%2&&printf("%d\t",d);}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Jelly, 14 bytes

ṢŒrH2¦€,ṪḂ$ƇƊḞ

Try it online!

Somehow, before I stepped back for a bit and questioned my decisions leading up to it, my original solution was going to be ṢŒrZd2¦2Zµ1,[2,1]œịⱮ,ṪṪ$Ƈ. I may have gotten a bit too attached to using divmod...

\$\endgroup\$
2
\$\begingroup\$

Brachylog, 18 bytes

ọ{÷₂ᵗ}ᵐ|ọ{t%₂1&h}ˢ

Try it online!

Generates the output, since it saves a byte over using a fork: ọ⟨{÷₂ᵗ}ᵐ≡{t%₂1&h}ˢ⟩

       |              The output is
ọ                     the list of pairs [unique element of input, # of occurrences]
 {   }ᵐ               with each pair
    ᵗ                 's last element
  ÷₂                  divided by 2 (rounding down),
       |              or
       |ọ             that same list of pairs
         {      }ˢ    filtered by
          t           the last element
           %₂         mod 2
             1        being 1,
         {    & }ˢ    and mapped to
               h      each pair's first element. 
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 18 bytes

{ÅγU©X2‰ø`.Áø,®sÏ,

Try it online!

{       sort input
Åγ      push run-length encoded input (count each element of input)
U©X     save compatibility number in ® and count in X
2‰      divmod count by 2 (for each compatibility number, get the count of pairs and info if a single sock is remaining)
ø       split that into a list of pair counts and a list of single socks
`       push those lists onto the stack
.Á      rotate the stack, so list of compatibility numbers and the list of pair counts are at the top of the stack
ø       zip them (for each compatibility number, get the pair count)
,       print that
®       push another list of compatibility numbers
s       swap with the list of single socks
Ï       keep only compatibility numbers of single socks
,       print that
\$\endgroup\$
2
\$\begingroup\$

Red, 169 bytes

func[a][b: copy[]m: copy#()foreach n a[alter b n unless
m/:n[put m n 0]m/:n: m/:n + 1]foreach k keys-of
m[t: m/:k either t = 1[remove/key m k][m/:k: t / 2]]insert b m b]

Doesn't work in TIO (Apparently remove/key is added only recently). It works fine in the Red GUI console:

enter image description here

#() is a map structure, the list of single socks is after it.

\$\endgroup\$
2
\$\begingroup\$

Japt, 17 16 bytes

ü
lu mÎp¡[XÎXÊz]

Output is an array of the format:
[O1,O2,...On,[[V1,P1],[V2,P2],...[Vn,Pn]]]
where Os are odds, Vs are values and Ps are pairs.

Try it (Footer formats the output for easier reading)

\$\endgroup\$
2
\$\begingroup\$

K4, 27 25 bytes

Solution:

(,#:'=&_p),,&p>_p:.5*#:'=

Example:

q)k)(,#:'=&_p),,&p>_p:.5*#:'=1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
2 3 4 5!1 1 2 2
1 3 5
// this is how a dictionary looks in the repl
q)k)*(,#:'=&_p),,&p>_p:.5*#:'=1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
2| 1
3| 1
4| 2
5| 2

Explanation:

(,#:'=&_p),,&p>_p:.5*#:'= / the solution
                        = / group input
                     #:'  / count (#:) each
                  .5*     / half (ie pair up)
                p:        / save as p
               _          / floor
             p>           / p > floor p? ie find whole pairs
            &             / where true
           ,              / enlist
          ,               / join
(        )                / do all this together
       _p                 / floor p
      &                   / where
     =                    / group
  #:'                     / count (#:) each
 ,                        / enlist

Extra:

  • -2 bytes thanks to ngn
\$\endgroup\$
  • 1
    \$\begingroup\$ ~p=f -> p>f \$\endgroup\$ – ngn Nov 24 at 13:55
  • 1
    \$\begingroup\$ &f -> &_p and rm f: \$\endgroup\$ – ngn Nov 24 at 13:57
  • 1
    \$\begingroup\$ consider 0W 2\: - it leads to a much shorter solution \$\endgroup\$ – ngn Nov 24 at 14:14
  • \$\begingroup\$ my tired brain cant work out something shorter with 0" 2\:, I'll try again tomorrow. thanks for the other golfs! \$\endgroup\$ – streetster Nov 24 at 17:35
  • 1
    \$\begingroup\$ ping me if you want me to reveal it. btw, the challenge now allows 0s in the first element of the result, as dict values. \$\endgroup\$ – ngn Nov 24 at 17:42
1
\$\begingroup\$

Charcoal, 50 bytes

≔⦃⦄ηFθ«F¬№υι«⊞υι§≔ηι⁰»§≔ηι⊕§ηι»IEυ⟦ι÷§ηι²⟧IΦυ﹪§ηι²

Try it online! Unfortunately I don't know how to get the deverbosifier to output ⦃⦄ (I just get «» when I try). Explanation:

≔⦃⦄η

Initialise a dictionary.

Fθ«

Loop over the socks.

F¬№υι

Test whether the compatibility number has been seen before. (Sadly Charcoal has no functions for determining dictionary keys, so I have to use a parallel list.)

«⊞υι§≔ηι⁰»

If it hasn't been seen then push the number to the list and zero out its dictionary entry.

§≔ηι⊕§ηι»

Increment the dictionary entry.

IEυ⟦ι÷§ηι²⟧

Output the number of pairs for each compatibility number. The compatibility number and number of pairs are output on separate lines, with each pair of numbers double-spaced.

IΦυ﹪§ηι²

Output those compatibility numbers with odd socks, each on their own line.

52 bytes for a deverbosifier-friendly version:

Fθ«≔Φυ⁼ι§κ⁰η¿η≔⊟ηη«≔⟦ι⁰⟧η⊞υη»UMη⁺κλ»IEυEι÷λ⊕μIΦυ﹪⊟ι²

Try it online! Link is to verbose version of code. Outputs the odd sock compatibility numbers double-spaced.

56 bytes for the original (IMHO better) condition that disallows printing zero pairs of socks:

Fθ«≔Φυ⁼ι§κ⁰η¿η≔⊟ηη«≔⟦ι⁰⟧η⊞υη»UMη⁺κλ»IΦEυEι÷λ⊕μ§ι¹IΦυ﹪⊟ι²

Try it online! Link is to verbose version of code.

Would be 43 bytes if Charcoal supported dictionary iteration:

≔⦃⦄ηFθ§≔ηι∨⬤η⁻ιλ⊕§ηιIΦEη⟦κ÷ι²⟧§ι¹IΦEηκ﹪§ηι²
\$\endgroup\$
1
\$\begingroup\$

Haskell, 112 bytes

import Data.List
f i=(\j->([(x,l`div`2)|(x,l)<-j,l>1],[x|(x,l)<-j,l`mod`2>0]))[(x,length s+1)|x:s<-group.sort$i]

Try it online!

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

Japt -Q, 16 bytes

ü
lu mÎuUmÎíUËÊz

Try it

Better solution that pairs list of first elements with list of lengths/2 using í instead of â.

Japt -Q, 14 16 bytes

ü
lu mÎuUËâDÊz h

Try it

output [sock , pairs num] list followed by odd socks.

ü            // sort and group input and save it
lu mÎ        // first element of groups of odd length
     u       // perpended by..
      UË     // imput mapped
        â    // unique elements
         DÊz h // concatenated to half of the length to string 

Thanks to @Shaggy for finding a bug. Unfortunately using â(x?) => x is concatenated before returning unique elements , so it failed with [2,2,2,2] case. Fixed by using h method which returns a string.

\$\endgroup\$
  • 1
    \$\begingroup\$ Unfortunately, this will fail if the number of pairs of an element is the same as the value of that element: petershaggynoble.github.io/Japt-Interpreter/… \$\endgroup\$ – Shaggy Nov 22 at 7:56
  • \$\begingroup\$ @Shaggy thanks for notifying me, should be fixed now \$\endgroup\$ – AZTECCO Nov 23 at 15:19
1
\$\begingroup\$

Lua, 144 142 bytes

load'r,p,o,i={},{},{},...for a=1,#i do r[i[a]]=(r[i[a]]or 0)+1 end;for a,b in pairs(r)do p[a],o[#o+1]=b//2,(b%2>0)and a or nil end;return p,o'

Try it online!

Function that takes list as argument and returns hashtable representing pairs and list of ones without match using Lua "multireturn".

Note: if there is only one sock of some color (poor guy), it still will go in pairs list with zero pairs. If this is not up to spec, please tell me (it will cost a bunch of bytes but is easily doable).

I personally consider return to be required, but results are also stored in globals p and o, so it in fact can be omitted.

\$\endgroup\$
  • \$\begingroup\$ replace nil with an unused variable like z to save 2 bytes \$\endgroup\$ – LuaNoob Nov 28 at 20:25
  • \$\begingroup\$ @LuaNoob Oops, missed it this time. Thanks for pointing put! \$\endgroup\$ – val says Reinstate Monica Nov 28 at 20:29
1
\$\begingroup\$

Perl 5, 82 bytes

sub{my%H;$H{$_}++for@_;delete@H{@A=grep$H{$_}%2,keys%H};map$_/=2,values%H;\%H,\@A}

Try it online!

(-ap), 73 bytes

Returning hash as key value pairs list

s/(\b\d+)( .*)(\b\1\b)/$H{$1}++;$2/e&&redo;delete@H{@F};$_="@{[%H]} | @F"

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ This doesn't print the pair counts \$\endgroup\$ – Malivil Nov 21 at 20:29
  • \$\begingroup\$ from my understandind it's not needed, it's to explain output \$\endgroup\$ – Nahuel Fouilleul Nov 22 at 7:36
  • 1
    \$\begingroup\$ fixed now 33 -> 82 bytes \$\endgroup\$ – Nahuel Fouilleul Nov 22 at 8:07
  • \$\begingroup\$ Why perl is somewhat special for me: it lies between totally unreadable code (alternative encodings/brainfuck) and hardly readable one in C/C++. I still see words but already have little idea what they do. \$\endgroup\$ – val says Reinstate Monica Nov 23 at 21:06
  • \$\begingroup\$ unreadable often because of special variables, regex and grammar. however first answer more functional is more readable \$\endgroup\$ – Nahuel Fouilleul Nov 24 at 7:38
1
\$\begingroup\$

Lua, 133 123 119 bytes (using global output var)

r,o,s={},{},{}for _=1,#t do d=t[_]r[d]=(r[d]or 0)+.5 end for a,b in pairs(r)do s[a],d=math.modf(b)o[#o+1]=d>0 and a end

Try it online!

Lua, 135 bytes (using output return)

r,o,s={},{},{}for _=1,#t do d=t[_]r[d]=(r[d]or 0)+.5 end for a,b in pairs(r)do s[a],d=math.modf(b)o[#o+1]=d>0 and a or x end return o,s

Try it online!

\$\endgroup\$
  • 3
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Taylor Scott Nov 22 at 13:04
  • 1
    \$\begingroup\$ Sadly, I do not think that taking input and output as variable is acceptable, but interesting approach for main code. \$\endgroup\$ – val says Reinstate Monica Nov 23 at 20:40
  • 1
    \$\begingroup\$ So you can output into variable? I don't think this is part of default I/O rules, but ok then… As for lambdas, every single function in Lua is lambda. Can you take input as variable or should it be a function argument? \$\endgroup\$ – val says Reinstate Monica Nov 23 at 21:27
  • \$\begingroup\$ Changed Code, saved more bytes, updated post with a notice. \$\endgroup\$ – LuaNoob Nov 24 at 16:07
  • \$\begingroup\$ @Malivil This is not even a function/lambda by the way. It is just a piece of code that inputs from a global variable and outputs into global variables. \$\endgroup\$ – val says Reinstate Monica Nov 24 at 16:26
1
\$\begingroup\$

Clojure, 102 bytes

(fn[d](def f(frequencies d))[(map(fn[[x y]][x(quot y 2)])f)(map first(filter #(=(mod(nth % 1)2)1)f))])

Try it online!

I really thought clojure would have a better chance. If only I had access to fmap. :-(

\$\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\$
  • 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 at 10:44
  • \$\begingroup\$ @JoKing: For me it's not outputting 0 on my computer. Strange. \$\endgroup\$ – stephanmg Nov 27 at 10:45
  • \$\begingroup\$ I will edit my answer for your suggestions. \$\endgroup\$ – stephanmg Nov 27 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 at 10:49
0
\$\begingroup\$

[Python 2.x or 3.x], 52 43 bytes (thanks to isaacg)

Retruns a Python dict with a tuple as value: (<pairs of socks>, <1 if a sock remains; 0 otherwise>). As fas as I understand this comment of the OP, this is now within spec. Please let me know if this is (still) not the case.

lambda s:{c:divmod(s.count(c),2)for c in s}

Try it online!

Output for the example case in the question:

{2: (4, 1), 3: (4, 0), 6: (2, 1), 0: (3, 1), 4: (3, 0), 9: (3, 0), 1: (4, 0), 7: (3, 1), 11: (3, 0), 13: (4, 0), 5: (3, 0), 12: (4, 0), 10: (2, 1), 8: (3, 0), 14: (2, 1)}
\$\endgroup\$
  • 1
    \$\begingroup\$ I don't think this is within spec; this doesn't list how many pairs there are for socks with odd-numbered counts. My understanding is that the output should consist of a list of pairs/counts, and a list of which socks have odd counts. This answer has the latter (sort of), but does not completely have the former. \$\endgroup\$ – Reinstate Monica Nov 21 at 20:02
  • \$\begingroup\$ @ReinstateMonica : you are completely right. My bad. I think I corrected it (and shaved one byte off in the process) - see above. \$\endgroup\$ – agtoever Nov 21 at 20:43
  • \$\begingroup\$ I still don't think I agree that the updated solution is to spec either, since it hasn't quite made a list of the socks that have odd counts per se... but then again, I'm not OP; maybe it is. \$\endgroup\$ – Reinstate Monica Nov 21 at 22:18
  • 1
    \$\begingroup\$ Assuming this approach is allowed (clarification needed), you can use the divmod function to save 8 bytes, and remove a space to save a ninth. \$\endgroup\$ – isaacg Nov 22 at 6:08
  • \$\begingroup\$ Also works in Python 3(.7) \$\endgroup\$ – pppery Dec 1 at 4:20

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.