I've been playing around with Scala recently and was thinking about how to implement a generic version of quicksort in it (just to get a better feeling for the language)
I came up with something like this
object Main {
def qs[T](a: List[T], f: (T, T) => Boolean): List[T] = {
if (a == Nil) return a
val (l, g) = a drop 1 partition (f(a(0),(_:T)))
qs(l, f) ::: List(a(0)) ::: qs(g, f)
}
def main(args: Array[String]): Unit = {
val a = List(5,3,2,1,7,8,9,4,6)
val qsInt = qs(_: List[Int], (_: Int) > (_: Int))
println(qsInt(a))
}
}
This is not as generic as I wanted it to be, since I have to explicitly state how to order the elements rather then just doing something like
val (l, g) = a drop 1 partition (a(0) >)
How can I tell the compiler that T only needs to implement the greater-than operator to be sortable by this function?
Regards
def qsort[T <% Ordered[T]](list: List[T]): List[T] = {
list match {
case Nil => Nil
case x::xs =>
val (before, after) = xs partition (_ < x)
qsort(before) ++ (x :: qsort(after))
}
}
Since Roger covered the Ordered case, let me cover Ordering:
def qsort[T](list: List[T])(implicit ord: Ordering[T]): List[T] = list match {
// import ord._ // enables "_ < x" syntax
case Nil => Nil
case x :: xs =>
val (before, after) = xs partition (ord.lt(_, x))
qsort(before) ::: x :: qsort(after)
}
Using Ordering has two main advantages:
The T type does not need to have been created as Ordered.
One can easily provide alternate orderings.
For instance, on Scala 2.8:
def sortIgnoreCase(strs: List[String]) = {
val myOrdering = Ordering.fromLessThan { (x: String, y: String) =>
x.toLowerCase < y.toLowerCase
}
qsort(strs)(myOrdering)
}
Related
Here is my program structure
type myType struct {
Attr map[string]any
// some other variables
}
func (t *Tran) foo () {
// some logic
count := 0
for i, v := range myArray {
count = t.boo(i, v, count)
}
}
func (t *Tran) boo (i int, v string, count int) int {
// bunch of logic
e := myType{}
if v == "special" {
e.Attr = map[string]any{"num": count}
count += 1
else {
e.Attr = map[string]any{}
}
t.state[i] = e
return count
}
Notice the count variable increments based on the "special" string. The program works fine. But I feel there might be smarter way to implement this count state variable. Also Foo can be called many times.
Any advice?
i'm fairly new to golang and im having trouble finding the most common string in an array (Windrichting). it should be N but my output gives me W (it always gives me the last string so Windrichting[6]. Can someone help?
this is my code:
package main
import "fmt"
func main() {
Windrichting := [7]string{"N", "N", "N", "N", "O", "Z", "W"}
windEL, winner := Mostcommon(Windrichting)
fmt.Printf("Mostcommon windrichting: %s\n", windEL)
fmt.Printf("Komt %d x voor\n", winner)
}
func Mostcommon(Windrichting [7]string) (windEL string, winner int) {
var N int
var O int
var Z int
var W int
Windrichtingbase := [4]string{"N", "O", "Z", "W"}
for _, v := range Windrichting {
switch v {
case Windrichtingbase[0]:
N++
if N > winner {
N = winner
windEL = "Noord"
}
case Windrichtingbase[1]:
O++
if O > winner {
O = winner
windEL = "Oost"
}
case Windrichtingbase[2]:
Z++
if Z > winner {
Z = winner
windEL = "Zuid"
}
case Windrichtingbase[3]:
W++
if W > winner {
W = winner
windEL = "West"
}
}
}
return windEL, winner
}
output
winner is always 0 and you never update it. then after incrementing your direction variables (N, O, Z and W), you immediately overwrite them with the zero value stored in winner. You need to reverse the order of the assignment.
Like in this change: https://go.dev/play/p/VaJgZcijFdh
Note also, that capitalized variables in Go mean they're exported
Here's an alternate implementation. It uses a histogram to collect the number of times a word appears. It then steps through the histogram to find the most common word. Nothing is hard-coded.
https://go.dev/play/p/wTFvNaPRP6B
It's quite common to compare data with precedence, for a struct which has multiple members which can be compared, or for a sort_by callback.
// Example of sorting a: Vec<[f64; 2]>, sort first by y, then x,
xy_coords.sort_by(
|co_a, co_b| {
let ord = co_a[1].cmp(&co_b[1]);
if ord != std::cmp::Ordering::Equal {
ord
} else {
co_a[0].cmp(&co_b[0])
}
}
);
Is there a more straightforward way to perform multiple cmp functions, where only the first non-equal result is returned?
perform multiple cmp functions, where only the first non-equal result is returned
That's basically how Ord is defined for tuples. Create a function that converts your type into a tuple and compare those:
fn main() {
let mut xy_coords = vec![[1, 0], [-1, -1], [0, 1]];
fn sort_key(coord: &[i32; 2]) -> (i32, i32) {
(coord[1], coord[0])
}
xy_coords.sort_by(|a, b| {
sort_key(a).cmp(&sort_key(b))
});
}
Since that's common, there's a method just for it:
xy_coords.sort_by_key(sort_key);
It won't help your case, because floating point doesn't implement Ord.
One of many possibilities is to kill the program on NaN:
xy_coords.sort_by(|a, b| {
sort_key(a).partial_cmp(&sort_key(b)).expect("Don't know how to handle NaN")
});
See also
Using max_by_key on a vector of floats
How to do a binary search on a Vec of floats?
There are times when you may not want to create a large tuple to compare values which will be ignored because higher priority values will early-exit the comparison.
Stealing a page from Guava's ComparisonChain, we can make a small builder that allows us to use closures to avoid extra work:
use std::cmp::Ordering;
struct OrdBuilder<T> {
a: T,
b: T,
ordering: Ordering,
}
impl<T> OrdBuilder<T> {
fn new(a: T, b: T) -> OrdBuilder<T> {
OrdBuilder {
a: a,
b: b,
ordering: Ordering::Equal,
}
}
fn compare_with<F, V>(mut self, mut f: F) -> OrdBuilder<T>
where F: for <'a> FnMut(&'a T) -> V,
V: Ord,
{
if self.ordering == Ordering::Equal {
self.ordering = f(&self.a).cmp(&f(&self.b));
}
self
}
fn finish(self) -> Ordering {
self.ordering
}
}
This can be used like
struct Thing {
a: u8,
}
impl Thing {
fn b(&self) -> u8 {
println!("I'm slow!");
42
}
}
fn main() {
let a = Thing { a: 0 };
let b = Thing { a: 1 };
let res = OrdBuilder::new(&a, &b)
.compare_with(|x| x.a)
.compare_with(|x| x.b())
.finish();
println!("{:?}", res);
}
Very simple algorithm in scala
def listReplication(num: Int, arr: List[Int]): List[Int] = {
val l = new ListBuffer[Int]()
for (a <- arr.indices) {
for (b <- 1 to num) {
l += arr.apply(a)
}
}
l.toList
}
Can it writes in immutable ?
Cannot use recursion
Thanks
Cat skinning one-liner
def listReplication(num: Int, arr: List[Int]):List[Int] =
arr.flatMap(a=>List.fill(num)(a))
You can use the for { ... } yield syntax to traverse any collection (or Cartesian product of collections) and produce a new collection, with no mutable data:
def listReplication(num: Int, arr: List[Int]): List[Int] = {
for {
a <- arr
b <- 1 to num
} yield a
}
Is there a way to convert a string (e.g. "+", "-", "/", "*") into their respective math operators (+, -, /, *)?
In Python you can do:
import operator
ops = {"+": operator.add, "-": operator.sub} # etc.
print ops["+"](1,1) # prints 2
Is there a similar library or method for Go?
You can do this with function values:
ops := map[string]func(int, int) int{
"+": func(a, b int) int { return a + b },
"-": func(a, b int) int { return a - b },
"*": func(a, b int) int { return a * b },
"/": func(a, b int) int { return a / b },
}
fmt.Println(ops["+"](4, 2))
fmt.Println(ops["-"](4, 2))
fmt.Println(ops["*"](4, 2))
fmt.Println(ops["/"](4, 2))
Output: Go Playground
6
2
8
2
For a nice print:
a, b := 4, 2
for op, fv := range ops {
fmt.Printf("%d %s %d = %d\n", a, op, b, fv(a, b))
}
Output:
4 / 2 = 2
4 + 2 = 6
4 - 2 = 2
4 * 2 = 8
There are few options but I would recommend just constructing the problem in a switch or using a map[string]func to provide a function which does the same. So... Either this;
ops := map[string]func(int, int) int{
"+": func(a, b int) int { return a + b },
"-": func(a, b int) int { return a - b },
"*": func(a, b int) int { return a * b },
"/": func(a, b int) int { return a / b },
}
or this;
func doOp(string op, lhs, rhs int) int {
switch (op) {
case "+":
return lhs + rhs
// ect
default:
// error cause they gave an unknown op string
}
}
Which I use would probably depend on scope. The function imo is more portable. The map isn't read only so for example someone else could just hose it entirely by assigning a different method to "+".
EDIT: After thinking about it the map sucks and I'd recommend against it. The function is more clear, stable, consistent, predictable, encapsulated ect.
Here's another implementation. This is give or take 3x faster than the string-based switch implementation but readability is a little less.
func RunOp(sign string, a, b int) int {
s := byte(sign[0])
switch s {
case byte(43):
return a+b
case byte(45):
return a-b
case byte(47):
return a/b
case byte(42):
return a*b
default:
return 0
}
}