re: Daily Coding Puzzles - Nov 4th - Nov 9th VIEW POST

FULL DISCUSSION
 

Wednesday

Array.diff (6 KYU):

Your goal in this kata is to implement a difference function, which subtracts one list from another and returns the result.

CodeWars

 

Python!

def array_diff(a, b):
    return [l for l in a if l not in b]
 
 

Or with sets!

def array_diff(a, b):
    return list(set(a) - set(b))
 

Here's one in Dart:

arrayDiff(List a, List b) => a..retainWhere((i) => !b.contains(i));
 

PowerShell

$a | ? { $_ -notin $b }

Expanding the ? alias:

$a = @(1,2,3,4)
$b = @(2,3,4,5)

$a | Where-Object { $_ -notin $b }
 

It wasn't as easy as doing a set difference as the a needed to keep the duplicate values.

Below is the answer in C#.

Where is the same as filter in JavaScript.

using System.Linq;
using System.Collections.Generic;

public class Kata
{
  public static int[] ArrayDiff(int[] a, int[] b)
  {
    var hash = new HashSet<int>(b);
    return a.Where(_ => !hash.Contains(_)).ToArray();
  }
}
 
 

Common Lisp

I'll use lists because... well, it's Lisp, right?

(set-difference '(1 2 2 2 3) '(2))
;; => (3 1)

Can't beat a good standard library ;)

 

Rust

  • With Liftime. The returned Vec<&T> has elements borrowed and valid until the list1 is valid.
fn diff<'a, T>(list1: &'a [T], list2: &[T]) -> Vec<&'a T>
where
    T: PartialEq,
{
    list1.into_iter().filter(|e| !list2.contains(e)).collect()
}
  • Without lifetime We return a new Vec free from any list provided, by cloning the data. The generic data type only allows the data type that implements Clone trait to be passed.
fn diff2<T>(list1: &[T], list2: &[T]) -> Vec<T>
where
    T: PartialEq + Clone,
{
    list1
        .into_iter()
        .map(|x| x.clone())
        .filter(|e| !list2.contains(&e))
        .collect()
}
 

APL

 a ~ b 

Replied to the post instead of the comment! My bad!

 

Haskell

array_diff :: Eq a => [a] -> [a] -> [a] 
array_diff a b = filter (\x -> notElem x b) a
 

Another Haskell solution:

array_diff :: Eq a => [a] -> [a] -> [a]
array_diff a b = [x | x <- a, x `notElem` b]
 

F#

let diff a b =
    a |> Array.filter (fun v -> not (b |> Array.contains v))

also sequence expression syntax

let diff a b =
    [|
        for value in a do
            if not (b |> Array.contains value) then
                yield value
    |]
 

Or (although it will also remove duplicates from a):

(a |> Set.ofSeq) - (b |> Set.ofSeq)

Yes, this was my first thought, but I was trying to retain dupes.

 
 
 

On the other hand, Ruby probably allocated about 10,000 object references under the hood and used 1gb of memory to make that happen. 😄

Honestly, I just came out here to have a good time and I'm feeling so attacked right now 😅😅😅

Haha nice. Honestly, I'm just so used to copy/pasting emojis from slack and discord. Fun fact, when you do that, it copies the colon emoji syntax, not the unicode glyph 😅🙃

@bendhalpern some numbers (using /usr/bin/time -l on OSX):

Go: 0.0s, 1.5Mb
Go run: 0.10s, 24Mb
Node: 0.06s, 19Mb
Ruby: 0.08s, 11Mb
Crystal: 0.0s, 1.5Mb
Crystal run: 0.4s, 10.4Mb
Rust: 0.00s - 1.12MiB
Rust (nightly): 0.01s - 0.88MiB
Go: 0.00s - 1.64MiB
Go run: 0.25s - 24.11MiB
Python: 0.21s - 5.48MiB

Disclaimer: I'm inexperienced with Go; using the example from below 😅

Oh, I know almost nothing about Go. I'm specifically using these exercises to learn the syntax. No clue if and how what I'm doing can be optimized. Go is famously, weirdly restrictive and intentionally verbose.

 
 
 
 

Go

func Difference(a []int, b []int) (diff []int) {
    m := make(map[int]bool)

    for _, item := range b {
        m[item] = true
    }

    for _, item := range a {
        if _, presence := m[item]; !presence {
            diff = append(diff, item)
        }
    }
    return
}
 
 
function array_diff(a, b) {
  let counter = {};
  for(let i of b) {
    counter[i] = true;
  }
  let result = a.filter(item => counter[item] !== true);
  return result;
}
 
code of conduct - report abuse