Proper Rust match idiom - recursion

I realize the language is at 0.9/0.10 and undergoing breaking changes still (like dropping do this week?), but am curious to know if I'm using sound idiomatics here. I've implemented two versions of the change-making algorithm, one naive and one that looks 'better' in my opinion.
This is for 0.9. Both snippets compile and yield identical results in a couple assert!'s
fn count_change_naive(cents: int, coins: &[int]) -> int {
if (cents == 0) {
1
} else if (cents < 0) {
0
} else {
if coins.iter().len() > 0 {
let new_amount: int = cents - coins[0];
let coins_tailed: &[int] = coins.tail();
count_change_naive(cents, coins_tailed) + count_change_naive(new_amount, coins)
} else {
0
}
}
}
That's pretty unwieldy IMO. I tried to implement the following:
fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
match cents {
n if cents == 0 => 1,
n if cents < 0 => 0,
n if coins.iter().len() > 0 => {
let new_amount: int = cents - coins[0];
let coins_tailed: &[int] = coins.tail();
count_change_idiomatic(cents, coins_tailed) + count_change_idiomatic(new_amount, coins)
},
_ => 0
}
}
I get unused variable warnings on account of the n in the match, but I'm uncertain how to avoid this without an ugly if-else pyramid. Can it be done? Am I missing anything significant in the second implementation?
EDIT: have cleaned up some to meet some of the suggestions, but left intact for comparision

To no get the warnings for the variable you have no use for, you just don't use it:
fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
match cents {
_ if cents == 0 => 1,
_ if cents < 0 => 0,
_ if coins.iter().len() > 0 => {
let new_amount: int = cents - coins[0];
let coins_tailed: &[int] = coins.tail();
count_change_idiomatic(cents, coins_tailed) + count_change_idiomatic(new_amount, coins)
},
_ => 0
}
}

You can use pattern matching on vectors to avoid the length-taking, indexing and tailing:
fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
match (cents, coins) {
(0, _) => 1,
_ if cents < 0 => 0,
(_, [first, .. coins_tailed]) => {
let new_amount = cents - first;
count_change_idiomatic(cents, coins_tailed) +
count_change_idiomatic(new_amount, coins)
}
_ => 0
}
}
The .. part of the pattern matches the rest of the vector (in this case, everything but the first element).

Here's a significant simplification of things, improving various idiomatic things:
fn count_change_naive(cents: int, coins: &[int]) -> int {
if cents == 0 {
1
} else if cents < 0 {
0
} else if coins.len() > 0 {
let new_amount = cents - coins[0];
let denom_tailed = coins.tail();
count_change_naive(cents, denom_tailed) + count_change_naive(new_amount, coins)
} else {
0
}
}
avoid return when it's not necessary;
no parentheses around the conditions in if statements
four spaces instead of two (standard Rust community style)
reduce nesting of if/else things where possible (else { if A { B } else { C } } → else if A { B } else { C })
And another change I'd make with the appropriate information: liberal commenting of the meaning of things. Possibly even shifting the recursive calls into their own statements (this will often enhance readability and has no runtime cost):
let ???1 = count_change_naive(cents, demon_tailed);
let ???2 = count_change_naive(new_amount, coins);
???1 + ???2

Related

Climbing Stairs Problem ( Access of element in vector )

Below is a code for the problem of CLIMBING STAIRS https://leetcode.com/problems/climbing-stairs/
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n,0);
dp[0] = 1;
dp[1] = 2;
for(int i=2;i<n;i++){
dp[i] = dp[i-2]+dp[i-1];
}
return dp[n-1];
}
};
The code gives a RUNTIME ERROR of HEAP BUFFER OVERFLOW.
Looking at the code , if n==1 the code should return dp[n-1] i.e. dp[0] ,
but that does not seem to be the case.
I'm guessing the issue maybe related to access of elements in vector.
Can anyone please explain what could be the issue here ??
if n==1 the code should return dp[n-1] i.e. dp[0] , but that does not seem to be the case.
Yes.
But when n == 1, you call
dp[1] = 2;
so you access the second element when you have only one element.
And what about the case n <= 0 ?
So, maybe
int climbStairs(int n) {
if ( 0 >= 0 ) {
return ???;
} else if ( 1 == n ) {
return 1;
} else {
vector<int> dp(n,0);
dp[0] = 1;
dp[1] = 2;
for(int i=2;i<n;i++){
dp[i] = dp[i-2]+dp[i-1];
}
return dp[n-1];
}
}
The problem states the constraints are
1 <= n <= 45
You're going out of range when n is 1 (i.e. you only have dp[0] that scenario)

Implementing fizz buzz of higher order using maps in go lang?

I am trying to implement the fizz buzz problem using maps in go lang. However, this code requires improvement in its working. It keeps on printing undesired and redundant results due to the for loop that iterates over the map. I tried a lot of solutions but failed. Is it feasible without using any help of a slice of keys?
package main
import "fmt"
func fizzbuzz(i int) {
myMap:= make(map[int]string)
myMap[3] = "fizz"
myMap[5] = "buzz"
myMap[15] = "fizzbuzz"
for k,v:= range myMap{
if i%k==0 {fmt.Printf("%v \n",v)
} else {fmt.Printf("%v \n",i)}
}
}
func main() {
for i:=1;i<10000;i++ {
fizzbuzz(i)
}
}
With a map
With your rule set, the entire for loop should be to decide if the i number is to be replaced with a word. But you emit a result in each iteration. At most one result should be emitted by the for. If i is not dividable by any of the keys, then i should be emitted.
Keys may be multiples of others (e.g. 15 = 3 * 5), and if the i number is dividable by such a key, we want to emit the word associated with the greatest key. So the for loop should not emit anything, because if you find a good key, there may be a greater one. So the loop should just find the greatest good key.
After the loop you can check if any good key was found, and if so, emit the word associated with it, else emit the number:
var rules = map[int]string{
3: "fizz",
5: "buzz",
15: "fizzbuzz",
}
func fizzbuzz(i int) {
max := -1
for k := range rules {
if i%k == 0 && k > max {
max = k
}
}
if max < 0 {
fmt.Println(i)
} else {
fmt.Println(rules[max])
}
}
func main() {
for i := 1; i < 100; i++ {
fizzbuzz(i)
}
}
Output (try it on the Go Playground):
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz
fizz
...
With an ordered slice
You can get better performance if the rules are sorted by the keys descending, in which case you can check the keys in that order (greatest first), and then the first that qualifies will be the greatest. So you can emit the result immediately, and return.
If execution continues after the loop, we know no keys were good, we can emit the i number:
var rules = []struct {
n int
word string
}{
{15, "fizzbuzz"},
{5, "buzz"},
{3, "fizz"},
}
func fizzbuzz(i int) {
for _, rule := range rules {
if i%rule.n == 0 {
fmt.Println(rule.word)
return
}
}
fmt.Println(i)
}
Try this on the Go Playground.
General (excluding multiples from rules)
Although you started with a rule set where 15 = 3 * 5 was included in the rules, this should not be the case; you should only list 3 and 5, 15 should be implicit.
In this case, you have to check all the rules of course, because each good key should emit a word. And you have to remember if a good key was found, and only emit the i number otherwise.
This is how you can do it:
var rules = []struct {
n int
word string
}{
{3, "fizz"},
{5, "buzz"},
}
func fizzbuzz(i int) {
found := false
for _, rule := range rules {
if i%rule.n == 0 {
found = true
fmt.Print(rule.word)
}
}
if !found {
fmt.Print(i)
}
fmt.Println()
}
Try it on the Go Playground.
Note: in this solution you could also use a map instead of the slice; the reason why I used a slice is so that in case of multiple good keys the emitted words will always be in the same order (defined by increasing keys), as iteration order of keys in a map is not defined. For details, see Why can't Go iterate maps in insertion order?
As mentioned, the order of items in a map, is not deterministic in Go. Though here are some simple solutions:
func fizzbuzz(n int) {
for i := 1; i <= n; i++ {
switch {
case i%15 == 0:
println("fizzbuzz")
case i%5 == 0:
println(`buzz`)
case i%3 == 0:
println(`fizz`)
default:
println(i)
}
}
}
func fizzbuzzList(n int) []string {
var res []string
for i := 1; i <= n; i++ {
switch {
case i%15 == 0:
res = append(res, `fizzbuzz`)
case i%5 == 0:
res = append(res, `buzz`)
case i%3 == 0:
res = append(res, `fizz`)
default:
res = append(res, strconv.Itoa(i))
}
}
return res
}
func fizzbuzzLazy(n int) chan string {
var res = make(chan string)
go func() {
for i := 1; i <= n; i++ {
switch {
case i%15 == 0:
res <- `fizzbuzz`
case i%5 == 0:
res <- `buzz`
case i%3 == 0:
res <- `fizz`
default:
res <- strconv.Itoa(i)
}
}
close(res)
}()
return res
}
And usage:
fizzbuzz(20)
for _, v := range fizzbuzzList(20) {
println(v)
}
for v := range fizzbuzzLazy(20) {
println(v)
}

Is there a way to optimize this code so it doesn't overflow the stack?

I am working on the third Project Euler problem:
fn main() {
println!("{}", p3());
}
fn p3() -> u64 {
let divs = divisors(1, 600851475143, vec![]);
let mut max = 0;
for x in divs {
if prime(x, 0, false) && x > max {
max = x
}
}
max
}
fn divisors(i: u64, n: u64, div: Vec<u64>) -> Vec<u64> {
let mut temp = div;
if i * i > n {
temp
} else {
if n % i == 0 {
temp.push(i);
temp.push(n / i);
}
divisors(i + 2, n, temp)
}
}
fn prime(n: u64, i: u64, skip: bool) -> bool {
if !skip {
if n == 2 || n == 3 {
true
} else if n % 3 == 0 || n % 2 == 0 {
false
} else {
prime(n, 5, true)
}
} else {
if i * i > n {
true
} else if n % i == 0 || n % (i + 2) == 0 {
false
} else {
prime(n, i + 6, true)
}
}
}
The value 600851475143 is the value that is at some point causing it to overflow. If I replace that with any value that is in the 1010 order of magnitude or less, it returns an answer. While keeping it as a recursive solution, is there any way to either:
Increase the stack size?
Optimize my code so it doesn't return a fatal runtime: stack overflow error?
I know this can be done iteratively, but I'd prefer to not do that.
A vector containing 600 * 109 u64s means you'll need 4.8 terabytes of RAM or swapspace.
I'm sure you don't need that for this problem, you're missing some knowledge of math here: scanning till the square root of the 600851475143 will be sufficient. You may also speed up the program by using the Sieve of Eratosthenes.
Project Euler is nice to sharpen your math skills, but it doesn't help you with any programming language in particular. For learning Rust I started with Exercism.
Performing some optimizations, such as going just up to the square root of the number when checking for its factors and for whether it's a prime, I've got:
fn is_prime(n: i64) -> bool {
let float_input = n as f64;
let upper_bound = float_input.sqrt() as i64;
for x in 2..upper_bound + 1 {
if n % x == 0 {
return false;
}
}
return true;
}
fn get_factors(n: i64) -> Vec<i64> {
let mut factors: Vec<i64> = Vec::new();
let float_input = n as f64;
let upper_bound = float_input.sqrt() as i64;
for x in 1..upper_bound + 1 {
if n % x == 0 {
factors.push(x);
factors.push(n / x);
}
}
factors
}
fn get_prime_factors(n: i64) -> Vec<i64> {
get_factors(n)
.into_iter()
.filter(|&x| is_prime(x))
.collect::<Vec<i64>>()
}
fn main() {
if let Some(max) = get_prime_factors(600851475143).iter().max() {
println!("{:?}", max);
}
}
On my machine, this code runs very fast with no overflow.
./problem003 0.03s user 0.00s system 90% cpu 0.037 total
If you really don't want the iterative version:
First, make sure that you compile with optimizations (rustc -O or cargo --release). Without it there's no chance for TCO in Rust. Your divisors function is tail-recursive, but it seems that moving this Vec up and down the recursion stack is confusing enough for LLVM to miss that fact. We can help the compiler a little, by using just a reference here:
fn divisors(i: u64, n: u64, mut div: Vec<u64>) -> Vec<u64> {
divisors_(i, n, &mut div);
div
}
fn divisors_(i: u64, n: u64, div: &mut Vec<u64>) {
if i * i > n {
} else {
if n % i == 0 {
div.push(i);
div.push(n / i);
}
divisors_(i + 2, n, div)
}
}
On my machine that changes make the code no longer segfault.
If you want to increase the stack size anyway, you should run your function in a separate thread with increased stack size (using std::thread::Builder::stack_size)
Rust has reserved the become keyword for guaranteed tail recursion,
so maybe in the future you'll just need to add one keyword to your code to make it work.

Longest, consequent, ascending subsequence of an array

I am stuck doing an assignment for university. The task is to find a recursive and then dynamic programming way to calculate the length of the longest,consequent,ascending subsequence of an array. If the array for example is: {4 , -5 , -3, -2, 5, -2, 0, 3 , 2} the maximal length would be 4 with the subsequence {-5, -3, -2, 5}. I have trouble finding a recursive way and without a recursive way it's impossible to find a dynamnic way for me.
I have tried programming something but I know it's wrong and I am not sure how to fix it:
public static int length(int[] arr,int j)
{
if(arr.length == 1)
{
return 1;
}
if(j == 1)
{
if(arr[j-1] < arr[j])
{
return 1;
}
else
{
return 0;
}
}
else
{
int c = length(arr,j-1);
if(arr[j-1] < arr[j])
{
return 1 + c;
}
else
{
return 0;
}
}
}
Try this :
int length(int index, int previous)
{
if(arr.length == (index+1))
return 0;
else
if(arr[index] > previous)
return 1+length(index+1,arr[index]);
else return length(index+1,previous)
}
Maybe you don't need to give the array as argument in each recursive call by making a static variable,
Previous is the latest element of the subsequence

How to eliminate this type of recursion?

This is a bit more intricate than a simple left-recursion or tail-call recursion. So I'm wondering how I can eliminate this kind of recursion. I'm already keeping my own stack as you can see below, so the function needs to no params or return values. However, it's still calling itself up (or down) to a certain level and I want to turn this into a loop, but been scratching my head over this for some time now.
Here's the simplified test case, replacing all "real logic" with printf("dostuff at level #n") messages. This is in Go but the problem is applicable to most languages. Use of loops and goto's would be perfectly acceptable (but I played with this and it gets convoluted, out-of-hand and seemingly unworkable to begin with); however, additional helper functions should be avoided. I guess I should to turn this into some kind of simple state machine, but... which? ;)
As for the practicality, this is to run at about 20 million times per second (stack depth can range from 1 through 25 max later on). This is a case where maintaining my own stack is bound to be more stable / faster than the function call stack. (There are no other function calls in this function, only calculations.) Also, no garbage generated = no garbage collected.
So here goes:
func testRecursion () {
var root *TMyTreeNode = makeSomeDeepTreeStructure()
// rl: current recursion level
// ml: max recursion level
var rl, ml = 0, root.MaxDepth
// node: "the stack"
var node = make([]*TMyTreeNode, ml + 1)
// the recursive and the non-recursive / iterative test functions:
var walkNodeRec, walkNodeIt func ();
walkNodeIt = func () {
log.Panicf("YOUR ITERATIVE / NON-RECURSIVE IDEAS HERE")
}
walkNodeRec = func () {
log.Printf("ENTER LEVEL %v", rl)
if (node[rl].Level == ml) || (node[rl].ChildNodes == nil) {
log.Printf("EXIT LEVEL %v", rl)
return
}
log.Printf("PRE-STUFF LEVEL %v", rl)
for i := 0; i < 3; i++ {
switch i {
case 0:
log.Printf("PRECASE %v.%v", rl, i)
node[rl + 1] = node[rl].ChildNodes[rl + i]; rl++; walkNodeRec(); rl--
log.Printf("POSTCASE %v.%v", rl, i)
case 1:
log.Printf("PRECASE %v.%v", rl, i)
node[rl + 1] = node[rl].ChildNodes[rl + i]; rl++; walkNodeRec(); rl--
log.Printf("POSTCASE %v.%v", rl, i)
case 2:
log.Printf("PRECASE %v.%v", rl, i)
node[rl + 1] = node[rl].ChildNodes[rl + i]; rl++; walkNodeRec(); rl--
log.Printf("POSTCASE %v.%v", rl, i)
}
}
}
// test recursion for reference:
if true {
rl, node[0] = 0, root
log.Printf("\n\n=========>RECURSIVE ML=%v:", ml)
walkNodeRec()
}
// test non-recursion, output should be identical
if true {
rl, node[0] = 0, root
log.Printf("\n\n=========>ITERATIVE ML=%v:", ml)
walkNodeIt()
}
}
UPDATE -- after some discussion here, and further thinking:
I just made up the following pseudo-code which in theory should do what I need:
curLevel = 0
for {
cn = nextsibling(curLevel, coords)
lastnode[curlevel] = cn
if cn < 8 {
if isleaf {
process()
} else {
curLevel++
}
} else if curLevel == 0 {
break
} else {
curLevel--
}
}
Of course the tricky part will be filling out nextsibling() for my custom use-case. But just as a general solution to eliminating inner recursion while maintaining the depth-first traversal order I need, this rough outline should do so in some form or another.
I'm not really sure I understand what it is you want to do since your recursion code looks a little strange. However if I understand the structure of your TMyTreeNode then this is what I would do for a non recursive version.
// root is our root node
q := []*TMyTreeNode{root}
processed := make(map[*TMyTreeNode]bool
for {
l := len(q)
if l < 1 {
break // our queue is empty
}
curr := q[l - 1]
if !processed[curr] && len(curr.childNodes) > 0 {
// do something with curr
processed[curr] = true
q = append(q, curr.childNodes...)
continue // continue on down the tree.
} else {
// do something with curr
processed[curr] = true
q := q[:l-2] // pop current off the queue
}
}
NOTE: This will go arbitrarily deep into the structure. If that's not what you want it will need some modifications.

Resources