I have 3 char "abc".
All combinations with these 3 characters are 3^3 = 27:
aaa, aab, aac, aba, ... etc.
I write a pseudo-code to print all of these combinations:
string dictionary[3] = {"a", "b", "c"};
string str[3];
for (i=0;i<3;++i) {
str[0]=dictionary[i];
for (j=0;j<3;++j) {
str[1]=dictionary[j];
for(k=0;k<3;++k) {
str[2]=dictionary[k];
println(str);
}
}
}
Now, I can see that all loops start at 0 and end at 2.
So I thought there was a way to make this function as a recursive function, although in fact no basic step can be distinguished.
So, i asked myself:
Is it really possible to create a recursive function for this type of problem?
If it existed, would it be more or less efficient than the iterative method?
If the number of usable chars would increase, performance would be worse or better?
Related
I have a vector of type UInt8 and fixed length 10. I think it contains a null-terminated string but when I do String(v) it shows the string + all of the zeros of the rest of the vector.
v = zeros(UInt8, 10)
v[1:5] = Vector{UInt8}("hello")
String(v)
the output is "hello\0\0\0\0\0".
Either I'm packing it wrong or reading it wrong. Any thoughts?
I use this snippet:
"""
nullstring(Vector{UInt8})
Interpret a vector as null terminated string.
"""
nullstring(x::Vector{UInt8}) = String(x[1:findfirst(==(0), x) - 1])
Although I bet there are faster ways to do this.
You can use unsafe_string: unsafe_string(pointer(v)), this does it without a copy, so is very fast. But #laborg's solution is better in almost all cases, because it's safe.
If you want both safety and maximal performance, you have to write a manual function yourself:
function get_string(v::Vector{UInt8})
# Find first zero
zeropos = 0
#inbounds for i in eachindex(v)
iszero(v[i]) && (zeropos = i; break)
end
iszero(zeropos) && error("Not null-terminated")
GC.#preserve v unsafe_string(pointer(v), zeropos - 1)
end
But eh, what are the odds you REALLY need it to be that fast.
You can avoid copying bytes and preserve safety with the following code:
function nullstring!(x::Vector{UInt8})
i = findfirst(iszero, x)
SubString(String(x),1,i-1)
end
Note that after calling it x will be empty and the returned value is Substring rather than String but in many scenarios it does not matter. This code makes half allocations than code by #laborg and is slightly faster (around 10-20%). The code by Jacob is still unbeatable though.
I came across this while doing the 2018 Advent of Code (Day 2, Part 1) solution in Rust.
The problem to solve:
Take the count of strings that have exactly two of the same letter, multiplied by the count of strings that have exactly three of the same letter.
INPUT
abcdega
hihklmh
abqasbb
aaaabcd
The first string abcdega has a repeated twice.
The second string hihklmh has h repeated three times.
The third string abqasbb has a repeated twice, and b repeated three times, so it counts for both.
The fourth string aaaabcd contains a letter repeated 4 times (not 2, or 3) so it does not count.
So the result should be:
2 strings that contained a double letter (first and third) multiplied by 2 strings that contained a triple letter (second and third) = 4
The Question:
const PUZZLE_INPUT: &str =
"
abcdega
hihklmh
abqasbb
aaaabcd
";
fn letter_counts(id: &str) -> [u8;26] {
id.chars().map(|c| c as u8).fold([0;26], |mut counts, c| {
counts[usize::from(c - b'a')] += 1;
counts
})
}
fn has_repeated_letter(n: u8, letter_counts: &[u8;26]) -> bool {
letter_counts.iter().any(|&count| count == n)
}
fn main() {
let ids_iter = PUZZLE_INPUT.lines().map(letter_counts);
let num_ids_with_double = ids_iter.clone().filter(|id| has_repeated_letter(2, id)).count();
let num_ids_with_triple = ids_iter.filter(|id| has_repeated_letter(3, id)).count();
println!("{}", num_ids_with_double * num_ids_with_triple);
}
Rust Playground
Consider line 21. The function letter_counts takes only one argument, so I can use the syntax: .map(letter_counts) on elements that match the type of the expected argument. This is really nice to me! I love that I don't have to create a closure: .map(|id| letter_counts(id)). I find both to be readable, but the former version without the closure is much cleaner to me.
Now consider lines 22 and 23. Here, I have to use the syntax: .filter(|id| has_repeated_letter(3, id)) because the has_repeated_letter function takes two arguments. I would really like to do .filter(has_repeated_letter(3)) instead.
Sure, I could make the function take a tuple instead, map to a tuple and consume only a single argument... but that seems like a terrible solution. I'd rather just create the closure.
Leaving out the only argument is something that Rust lets you do. Why would it be any harder for the compiler to let you leave out the last argument, provided that it has all of the other n-1 arguments for a function that takes n arguments.
I feel like this would make the syntax a lot cleaner, and it would fit in a lot better with the idiomatic functional style that Rust prefers.
I am certainly no expert in compilers, but implementing this behavior seems like it would be straightforward. If my thinking is incorrect, I would love to know more about why that is so.
No, you cannot pass a function with multiple arguments as an implicit closure.
In certain cases, you can choose to use currying to reduce the arity of a function. For example, here we reduce the add function from 2 arguments to one:
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn curry<A1, A2, R>(f: impl FnOnce(A1, A2) -> R, a1: A1) -> impl FnOnce(A2) -> R {
move |a2| f(a1, a2)
}
fn main() {
let a = Some(1);
a.map(curry(add, 2));
}
However, I agree with the comments that this isn't a benefit:
It's not any less typing:
a.map(curry(add, 2));
a.map(|v| add(v, 2));
The curry function is extremely limited: it chooses to use FnOnce, but Fn and FnMut also have use cases. It only applies to a function with two arguments.
However, I have used this higher-order function trick in other projects, where the amount of code that is added is much greater.
Problem:
A digital root is the recursive sum of all the digits in a number. Given n, take the sum of the digits of n. If that value has two digits, continue reducing in this way until a single-digit number is produced. This is only applicable to the natural numbers.
example:
digital_root(16)
=> 1 + 6
=> 7
This is a function that was coded:
function digital_root(n) {
if (n < 10) {
return n;
}
return digital_root( n.toString().split('').reduce( function (a, b) {
return a + +b;
}, 0));
}
Can someone clarify what the extra + is doing in this line of code? return a + +b;
Its probably a sneaky way of converting a string to an integer. You don't say what language this is, but many dynamic languages allow variables to be any type without declaration and use + for both addition and string concatenation, with implicit conversions between strings and numbers. Such languages make it easy to accidentally get the wrong thing (concatenating when you intend to add or vice versa).
However, using a unary + is (usually) a numeric identity, which will convert its argument to a number (if it happens to be a string -- it does nothing if the argument is already a number). So then the binary + will be add rather than concatenate.
Ok, recursion is giving me "coders block" I have 2 homework assignments this week, one of them is simply the following..
Design a function that accepts an integer argument and returns the sum of all the integers from
1 up to the number passed as an argument. For example, if 50 is
passed
as an argument, the fu
nction
will return the sum
of 1, 2, 3, 4,
...
.50
. Use the recursion to calculate the sum.
This is my solution... am I understanding how this works? The book is teaching us via some fake psuedocode so I know it's not "real" code....
Function Integer SumAll(Integer Number)
If Number > 0 Then
Return Number + SumAll(Number-1)
Else
Return 0
End If
End Function
OK I think this is it, I wrote this in c++ to test it out.
#include <iostream>
using namespace std;
int SumAll(int Number){
if (Number > 0) {
return Number + SumAll(Number-1);
}
}
int main(){
cout<<SumAll(2);
return 0;
}
Your C++ code is buggy because the base case needs to be treated in the recursive function itself.
Your pseudocode is basically correct except that it doesn't work when Number < 0; you should really have an error message in that case.
I agree with the comments that you cannot possibly work in the dark; use a real programming language. Your pseudocode looks a lot like Pascal, so maybe you can use Free Pascal here. Otherwise, I'd recommend Python.
In Python 3, the code would look like this:
def sum_all(number):
if number > 1:
return number + sum_all(number-1)
elif number == 1: # base case
return 1
else:
raise Exception("negative number")
print(sum_all(10))
which would correctly return 55.
When I made my studies, the teacher also used some kind of pseudocode similar to Pascal. We agreed very early on that I would use Turbo Pascal instead, and that helped me a lot because I was able to test things on the PC.
I just solved the first problem from Project Euler in JavaFX for the fun of it and wondered what block expressions are actually good for? Why are they superior to functions? Is it the because of the narrowed scope? Less to write? Performance?
Here's the Euler example. I used a block here but I don't know if it actually makes sense
// sums up all number from low to high exclusive which are divisible by a or b
function sumDivisibleBy(a: Integer, b: Integer, high: Integer) {
def low = if (a <= b) a else b;
def sum = {
var result = 0;
for (i in [low .. <high] where i mod a == 0 or i mod b == 0) {
result += i
}
result
}
}
Does a block make sense here?
Well, no, not really, it looks like extra complexity with no real benefit. Try removing the sum variable and the block and you will see that the code still works the same.
In general block expressions can be useful when you want to create an anonymous scope rather than factoring the code into a function, most of the time you should rather create a function.