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
}
Related
I have this code that does a brute-force search to find a match for a string:
fn main() {
let strings: Vec<String> = ["a", "b", "c","d","e","f","g","h","i","j","K","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"].map(String::from).to_vec();
for i in strings.iter(){
for j in strings.iter(){
for k in strings.iter(){
for l in strings.iter(){
let mut result = format!("{i}{j}{k}{l}");
println!("{}",result);
if result == "Kaio"{
println!("Found it!!");
return ;
}
}
}
}
}
}
Is there a better way to be doing this? Can I do it dynamically? In this example I use four loops, assuming that the final string has a length of four. But what if there's a dynamically-sized string that I don't know the size of?
The itertools crate gives a good macro to generate this in iproduct.
use itertools::iproduct;
fn main() {
let pool: Vec<String> = "abcdefghijklmnopqrstuvwxyz".chars().map(String::from).collect();
let possibilities: Vec<String> = iproduct!(&pool, &pool, &pool, &pool) // for four-letters
.map(|(a, b, c, d)| format!("{}{}{}{}", a, b, c, d))
.collect();
for password in possibilities {
if password == "eggs" {
println!("We found it!");
}
}
}
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?
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);
}
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
}
}
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)
}