a%b=abs$a-b
x@(a:b)#y@(c:d)|e:_<-d,a%c>a%e=x#d|1>0=a%c+b#y
_#_=0
Try it online!
Explanation
First we define (%)
to be the absolute difference between two numbers. Then we define (#)
to be the interesting function. In the first line we match when both lists are non-empty:
x@(a:b)#(c:d:e)
On our first case from here we bind d
to e:_
with e:_<-d
. This ensures that d
is non-empty and sets it's first element to e
.
Then if the second element of \$Y\$ (e
) is closer than the first (c
) to the first element of \$X\$ (a
), we return x#d
removing the first element of \$Y\$ and calling again with the same \$X\$.
If we match the pattern but don't pass the condition we do:
a%c+b#y
Which, removes the first item of \$X\$ and adds the absolute difference of it from the first element of \$X\$ to the remaining result.
Lastly if we don't match the pattern we return \$0\$. Not matching the pattern means that \$X\$ must be empty because \$Y\$ cannot be empty.
This algorithm has order notation \$O(|X|+|Y|)\$.
Here's how I would do it in \$O(\left|X\right|\times\left|Y\right|)\$ time:
x#y=sum[minimum$abs.(z-)<$>y|z<-x]
Try it online!
1 + 2 + 3
derived fromX = (1,2,3)
andY = (0,8)
? \$\endgroup\$1
,2
, and3
inY
is0
. Thus the differences are1-0
,2-0
,3-0
. \$\endgroup\$