Dart Generator Functions (yield / yield*) - dart

I am trying to understand how the generator functions work in dart/flutter.
There is a video from the flutter team Generator Functions - Flutter in Focus where they discuss the following example.
Iterable<int> getRange(int start, int finish) sync* {
if (start <= finish) {
yield start;
print('start: $start');
for (final val in getRange(start+1, finish)) {
yield val;
print('val: $val');
}
}
}
only without the print lines.
I went and called that function in a main like this
void main() async {
getRange(0, 3).forEach(print);
}
and got the following results:
0
start: 0
1
val: 1
start: 1
2
val: 2
val: 2
start: 2
3
val: 3
val: 3
val: 3
start: 3
The part from where I do not understand the output result is from
1
val: 1
start: 1
Why is the start: 1after the val: 1. I somehow do not get how the recursion in combination with the yield works. Also what happens when the yield val; gets read.

A good example of badly written code, doing strange things, is hard to understand because the code is badly written in the first place. To make debugging easier, I added the start variable to the print statements. Also removed async from your main() since nothing here is running asynchronously:
Iterable<int> getRange(int start, int finish) sync* {
if (start <= finish) {
yield start;
print('(start = $start) start: $start');
for (final val in getRange(start + 1, finish)) {
yield val;
print('(start = $start) val: $val');
}
}
}
void main() {
getRange(0, 3).forEach(print);
}
Which outputs:
0
(start = 0) start: 0
1
(start = 0) val: 1
(start = 1) start: 1
2
(start = 0) val: 2
(start = 1) val: 2
(start = 2) start: 2
3
(start = 0) val: 3
(start = 1) val: 3
(start = 2) val: 3
(start = 3) start: 3
So the part you are asking about is now:
1
(start = 0) val: 1
(start = 1) start: 1
An important detail in your program is that you are doing yield BEFORE print(). So when you are doing yield 1, the value will move to your print statement in main() as the first thing. You can then see that your for-loop will do the val print before asking for the next value which would make the start = 1 loop continue.
yield in sync* methods means the method deliver the value and stops executing the method until a new value is asked for.

Related

Delete N nodes after M nodes of a linked list

I can't figure out why my code is not working. The question is -
Delete N nodes after M nodes of a linked list
Input:
First line of input contains number of testcases T. For each testcase, first line of input contains number of elements in the linked list and next M and N respectively space separated. The last line contains the elements of the linked list.
Example:
Input:
1
8
2 1
9 1 3 5 9 4 10 1
Output:
9 1 5 9 10 1
And my code is -
void linkdelete(struct Node *head, int M, int N)
{
if(head==NULL)
return;
Node* temp=head;
while(1)
{
int m=M-1;
while(m--)
{
temp=temp->next;
if(temp==NULL)
exit;
}
int n=N;
Node* t2=temp;
while(n--)
{
t2=t2->next;
if(t2==NULL)
exit;
}
temp->next=t2->next;
temp=temp->next;
}
On compiling it's giving RUNTIME ERROR.
Some issues:
Your code has unbalanced braces. I suppose the missing closing brace should be at the end, but since you have not indented your code, there is no way to know
You should not exit. The function should return. In the second loop should not even even exit the function, but just break out of the loop: you still need to change temp->next.
The iteration of the outer loop may end with temp==NULL, so when it starts the next iteration, you will have an invalid reference with temp->next. Make the condition of the outer loop temp != NULL
Here is a corrected version:
void linkdelete(struct Node *head, int M, int N) {
if (head == NULL) return;
Node* temp = head;
while (temp != NULL) {
int m = M - 1;
while (m--) {
temp = temp->next;
if (temp == NULL) return; // don't exit, but return
}
Node* t2 = temp->next;
int n = N;
while (n--) {
if (t2 == NULL) break; // don't stop yet
t2 = t2->next;
}
temp->next = t2;
temp = t2;
}
}

Is there a more succinct way of performing the same task below? Rounding down to nearest 1 or 5mod6

var n = 27;
void main() {
while (n>=5)
if ( (n) % 3==0 && (n) % 2==0 ){
print(n-1);
break;
}
else if ( (n) % 3==0 && (n) % 2!=0 ){
print(n-2);
break;
}
else if ((n) % 3!=0 && (n) % 2==0){
print((n/6).floor()*6 +(1));
break;
}
else { n=n+1;}
}
I was looking for a way to have an input reduced to the nearest 1 or 5mod6 (for n>=5) and came up with the code above in Dart (project is in flutter). Does anyone have any better way of doing the same thing?
The result (rounded down input) will then be passed to another function.
For the current n value of 27 the console will print 25... try other values 24 maps to 23, 23 to itself, 22,21,20 to 19, 19 to itself, 18 to 17, 17 to itself, 16,15,14 to 13.....and I hope you get the idea.
I would get rid of the loop by finding the next lower multiple of 6 and then adding 1 or 5. The code ends up being shorter, and I think it expresses your intent much more clearly than code involving % 3 and % 2.
int lowerMultiple(int n, int multipleOf) =>
((n - 1) / multipleOf).floor() * multipleOf;
void main() {
var n = 27;
var m = lowerMultiple(n, 6);
print((n - m) >= 5 ? (m + 5) : (m + 1));
}
The above code should work for integers less than 5 as well, including non-positive ones.

Cleanest way to wrap array index?

Say I have an array of 5 Ints. What would be the most efficient way to wrap the index of the array if the index were incremented or decremented (for example) the following occurs?
where n = 0: arr[n-1] // -> arr[4] (wraps from 0 back to the end of the array)
where n = 2: arr[n+1] // -> arr[3] (behaves as normal)
where n = 4: arr[n+1] // -> arr[0] (wraps to 0 from the end of the array)
You can use the mod operation which will get you to a range of -count to count, then add count back in and mod again:
let foo = [0, 1, 2, 3, 4, 5]
for i in -6...7 {
print(i, foo[(i % foo.count + foo.count) % foo.count])
}
// -6 0
// -5 1
// -4 2
// -3 3
// -2 4
// -1 5
// 0 0
// 1 1
// 2 2
// 3 3
// 4 4
// 5 5
// 6 0
This works for both directions.
A bit late to the party, but if you're facing the same issue and have a lot of use cases for wrap-around array indices, you could also put the %-solution from the accepted answer in a simple subscript extension of Array, like so:
extension Array {
subscript (wrapping index: Int) -> Element {
return self[(index % self.count + self.count) % self.count]
}
}
Example Usage:
let array = ["a","b","c"]
print( array[wrapping: 0] ) // a
print( array[wrapping: 4] ) // b
print( array[wrapping: -1] ) // c
Cleanest I can do for only positive integers is this
extension Array{
subscript(wrapAround index: Int) -> Element {
return self[index % self.count]
}
}

why my code is slow when finding Fibonacci sum?

I'm writing answers for project Euler Questions in this repo
but having some performance issues in my solution
Question 2:
Each new term in the Fibonacci sequence is generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
My Solution is
func solution2()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
if (fibonacci(index) % 2 == 0)
{
sum += fibonacci(index)
}
}
print(sum)
}
My Question is, why it gets super slow after iteration 42, i want to do it for 4000000 as the question says, any help?
solution 2
func solution2_fast()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<4000000
{
print (index)
let f = findFibonacciNumber(Double(index))
if (f % 2 == 0)
{
sum += f
}
}
print(sum)
}
The most important thing about PE questions is to think about what it is asking.
This is not asking you to produce all Fibonacci numbers F(n) less than 4000000. It is asking for the sum of all even F(n) less than 4000000.
Think about the sum of all F(n) where F(n) < 10.
1 + 2 + 3 + 5 + 8
I could do this by calculating F(1), then F(2), then F(3), and so on... and then checking they are less than 10 before adding them up.
Or I could store two variables...
F1 = 1
F2 = 2
And a total...
Total = 3
Now I can turn this into a while loop and lose the recursion altogether. In fact, the most complex thing I'm doing is adding two numbers together...
I came up with this...
func sumEvenFibonacci(lessThan limit: Int) -> Int {
// store the first two Fibonacci numbers
var n1 = 1
var n2 = 2
// and a cumulative total
var total = 0
// repeat until you hit the limit
while n2 < limit {
// if the current Fibonacci is even then add to total
if n2 % 2 == 0 {
total += n2
}
// move the stored Fibonacci numbers up by one.
let temp = n2
n2 = n2 + n1
n1 = temp
}
return total
}
It runs in a fraction of a second.
sumEvenFibonacci(lessThan: 4000000)
Finds the correct answer.
In fact this... sumEvenFibonacci(lessThan: 1000000000000000000) runs in about half a second.
The second solution seems to be fast(er) although an Int64 will not be sufficient to store the result. The sum of Fibonacci numbers from 2..91 is 7,527,100,471,027,205,936 but the largest number you can store in an Int64 is 9,223,372,036,854,775,807. For this you need to use some other types like BigInteger
Because you use the recursive, and it cache in the memory.If you iteration 42, it maybe has so many fibonacci function in your memory, and recursive.So it isn't suitable for recursive, and you can store the result in the array, not the reason of the swift.
this is the answer in two different ways
func solution2_recursive()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
let f = fibonacci(index)
if( f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}
solution 2
func solution2()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<50
{
let f = findFibonacciNumber(Double(index))
if(f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}

Swift - Unexpected error in simple if statement

I'm new to Swift so this might turn out to be very simple, but I'll ask you anyway since I can't figure it out:
I was playing on the Playground and thought I'd write some lines of code in order to do this: generate a random number between two given values (a,b).
If, for example, a = 5 and b = 20, a random number between 5 and 20 is supposed to be generated.
But I get an unexpected error! I wrote these lines of code
var a = UInt32()
var b = UInt32()
var randomNumberInBetween = Int()
a = 5
b = 20
if (b - a) > 0 {
randomNumberInBetween = Int(arc4random_uniform(b - a) + a)
} else {
print("error", terminator: "")
}
Now:
If b > a (so that (b-a)>0 ) it works just fine.
If b = a it prints "error", so it works correctly.
BUT if a > b, so that (b-a)<0, it gives this error : "Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_l386_INVOP, subcode=0x0)."
screenshot
My question is: If (b-a)<0 shouldn't it just run the "else" part of the if statement and just print "error" ? Why does this error occur?
The UInt32 version of - has the signature: (UInt32, UInt32) -> UInt32.
7 - 9 is -2.
You can't express -2 with an unsigned type such as UInt32.
Try something like:
func random(inRange range: Range<Int>) -> Int {
return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound)))
}
func random(inRange range: ClosedRange<Int>) -> Int {
return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound + 1)))
}
print(random(inRange: 1..<10))

Resources