Use of uninitialized value of type Any in numeric context raku - raku

I've come across a programming question at reddit (Take a look at the link for the question)
This was one the solutions in Python:
s="112213"
k=2
result=0
for i in range(len(s)):
num_seen = 0
window = {}
for ind in range(i, len(s)):
if not s[ind] in window:
num_seen += 1
window[s[ind]] = 1
else:
window[s[ind]] += 1
if window[s[ind]] == k:
num_seen -= 1
if num_seen == 0:
result +=1
elif window[s[ind]] > k:
break
print(result)
I've tried to port this solution into Raku and here is my code:
my #s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^#s {
my $seen = 0;
my %window;
for #s[$_..*] {
if $^a == %window.keys.none {
$seen++;
%window{$^a} = 1;}
else {
%window{$^a} += 1;}
if %window{$^a} == $k {
$seen--;
if $seen == 0 {
$res++;} }
elsif %window{$^a} > $k {
last;}}}
say $res;
It gives this error:
Use of an uninitialized value of type Any in a numeric context in a block at ... line 13
How to fix it?

I don't feel that's a MRE. There are too many issues with it for me to get in to. What I did instead is start from the original Python and translated that. I'll add some comments:
my \s="112213" .comb; # .comb to simulate Python string[n] indexing.
my \k=2;
my $result=0; # result is mutated so give it a sigil
for ^s -> \i { # don't use $^foo vars with for loops
my $num_seen = 0;
my \window = {}
for i..s-1 -> \ind {
if s[ind] == window.keys.none { # usefully indent code!
$num_seen += 1;
window{s[ind]} = 1
} else {
window{s[ind]} += 1
}
if window{s[ind]} == k {
$num_seen -= 1;
if $num_seen == 0 {
$result +=1
}
} elsif window{s[ind]} > k {
last
}
}
}
print($result)
displays 4.
I'm not saying that's a good solution in Raku. It's just a relatively mechanical translation. Hopefully it's helpful.

As usual, the answer by #raiph is correct. I just want to do the minimal changes to your program that get it right. In this case, it's simply adding indices to both loops to make stuff clearer. You were using the context variable $_ in the first, and $^a in the second (inner), and it was getting unnecesarily confusing.
my #s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^#s -> $i {
my $seen = 0;
my %window;
for #s[$i..*] -> $c {
if $c == %window.keys.none {
$seen++;
%window{$c} = 1;
} else {
%window{$c} += 1;
}
if %window{$c} == $k {
$seen--;
if $seen == 0 {
$res++;
}
} elsif %window{$c} > $k {
last;
}
}
}
say $res;
As you see , besides trying to indent everything a bit more properly, the only additional thing is to add -> $i and -> $c so that loops are indexed, and then use them where you were using implicit variables.

Related

Variable interator in for cycle

This is my example
for (i in array.indices)
{
if (array[i] == 10)
{
i -= 2//have error here
}
}
How can i make 'i' variable mutable?
You can't. Use while loop instead:
var i = 0
while (i < array.size) {
if (array[i] == 10) {
i -= 2
}
...
i++
}

How to remake the program so that words are passed in function arguments in the KOTLIN programming language?

Need to create a function that implements the attached algorithm, to which all words are passed in the function arguments.
For example:
f ("dfd" dd "ddd");
My code:
fun main() {
var s = readLine();
var w = Array(128){0} //To mark characters from a word 1
var g = Array(128){0}//When we encounter a space, we add units from the first array to the corresponding elements of the second, zeroing them in the first.
if(s!=null)
{
for(c in s)
{
if(c.toInt() > 127 || c.toInt()<0) {
println("Input error, try again");
return;
}
//Checking for space.
if(c.toInt() != 32) w[c.toInt()] = 1;
else
for(k in 0..127)
{
if(w[k] == 1)
{
g[k] += 1;
w[k] = 0;
}
}
}
//For the last word, if there was no space after it.
for(k in 0..127)
{
if(w[k] == 1)
{
g[k] += 1;
w[k] = 0;
}
}
}
//Displaying matched characters to the screen
for(k in 0..127)
{
if(g[k]>1)
{
println(k.toChar());
}
}
}
This program searches for characters that match at least two words in a string
Example
input: hello world
output: lo
There's already utilities for these in Kotlin, I highly recommend you to read the docs before asking these type of questions.
The groupingBy should do what you want:
readLine()?.let { input ->
input.groupingBy { it }.eachCount()
.forEach { if (it.value > 1 && it.key != ' ') println(it.key) }
}

Why is there such a large performance difference between these two scrips that do the same thing?

This is problem36 from the Euler Project. Sum all of the numbers below a million that are palindromic in base 2 and base 10.
I'd originally tried solving it in a more functional style.
This runs in just under 6 seconds.
[1..1_000_000]
.grep( * !%% 2 )
.grep( -> $x { $x == $x.flip } )
.grep( -> $y { $y.base(2) == $y.base(2).flip } )
.sum.say
Surprisingly this took 12 seconds even though I'm only generating odd numbers and therefore
skipping the test for even.
(1,3 ... 1_000_000)
.grep( -> $x { $x == $x.flip } )
.grep( -> $y { $y.base(2) == $y.base(2).flip } )
.sum.say
This runs in about 3 seconds.
my #pals;
for (1,3 ... 1_000_000) -> $x {
next unless $x == $x.flip;
next unless $x.base(2) == $x.base(2).flip;
#pals.push($x);
}
say [+] #pals;
I also noted that there is a significant difference between using
for (1,3 ... 1_000_000) -> $x { ...
and
for [1,3 ... 1_000_000] -> $x { ...
Anyone know why the streaming versions are so much slower than the iterative one?
And, why would those two for loops be so different in performance?
The construct [...] is an array composer. It eagerly iterates the iterable found within it, and stores each value into the array. Only then do we proceed to do the iteration. That results in far more memory allocation and is less cache-friendly. By contrast, parentheses do nothing (aside from grouping, but they don't add any semantics beyond that). Thus:
[1..1_000_000]
.grep( * !%% 2 )
.grep( -> $x { $x == $x.flip } )
.grep( -> $y { $y.base(2) == $y.base(2).flip } )
.sum.say
Will allocate and set up a million element array and iterate it, while:
(1..1_000_000)
.grep( * !%% 2 )
.grep( -> $x { $x == $x.flip } )
.grep( -> $y { $y.base(2) == $y.base(2).flip } )
.sum.say
Runs rather faster, because it need not do that.
Further, the ... operator is currently far slower than the .. operator. It's not doomed to be that way forever, it's just received a lot less attention so far. Since .grep has also been decently well optimized, it turns out to be quicker to filter out the elements made by the range - for now, anyway.
Finally, using == to compare the (string) results of base and flip is not so efficient, since it parses them back into integers, when we could use eq and compare the strings:
(1 .. 1_000_000)
.grep(* !%% 2)
.grep( -> $x { $x eq $x.flip } )
.grep( -> $y { $y.base(2) eq $y.base(2).flip } )
.sum.say
If you want something that is faster, you can write your own sequence generator.
gather {
loop (my int $i = 1; $i < 1_000_000; $i += 2) {
take $i
}
}
.grep( -> $x { $x eq $x.flip } )
.grep( -> $y { $y.base(2) eq $y.base(2).flip } )
.sum.say
Which takes about 4 seconds.
Or to go even faster, you can create the Iterator object yourself.
class Odd does Iterator {
has uint $!count = 1;
method pull-one () {
if ($!count += 2) < 1_000_000 {
$!count
} else {
IterationEnd
}
}
}
Seq.new(Odd.new)
.grep( -> $x { $x == $x.flip } )
.grep( -> $y { $y.base(2) == $y.base(2).flip } )
.sum.say
Which only takes about 2 seconds.
Of course if you want to go as fast as possible, get rid of the sequence iteration entirely.
Also use native ints.
Also cache the base 10 string. (my $s = ~$x)
my int $acc = 0;
loop ( my int $x = 1; $x < 1_000_000; $x += 2) {
next unless (my $s = ~$x) eq $s.flip;
next unless $x.base(2) eq $x.base(2).flip;
$acc += $x
}
say $acc;
Which gets it down to about 0.45 seconds.
(Caching the .base(2) didn't seem to do anything.)
This is probably close to the minimum without resorting to using nqp ops directly.
I tried writing a native int bit flipper, but it made it slower. 0.5 seconds.
(I did not come up with this algorithm, I only adapted it to Raku. I also added the +> $in.msb to fit this problem.)
I would guess that spesh is leaving in operations that don't need to be there.
Or maybe it isn't JITting very well.
It might be more performant for values larger than 1_000_000.
(.base(2).flip is O(log n) whereas this is O(1).)
sub flip-bits ( int $in --> int ) {
my int $n =
((($in +& (my int $ = 0xaaaaaaaa)) +> 1) +| (($in +& (my int $ = 0x55555555)) +< 1));
$n = ((($n +& (my int $ = 0xcccccccc)) +> 2) +| (($n +& (my int $ = 0x33333333)) +< 2));
$n = ((($n +& (my int $ = 0xf0f0f0f0)) +> 4) +| (($n +& (my int $ = 0x0f0f0f0f)) +< 4));
$n = ((($n +& (my int $ = 0xff00ff00)) +> 8) +| (($n +& (my int $ = 0x00ff00ff)) +< 8));
((($n +> 16) +| ($n+< 16)) +> (32 - 1 - $in.msb)) +& (my int $ = 0xffffffff);
}
…
# next unless (my $s = ~$x) eq $s.flip;
next unless $x == flip-bits($x);
You can even try to use multiple threads.
Note that this workload is entirely too little for this to be effective.
The overhead of using threads swamps out any benefit.
my atomicint $total = 0;
sub process ( int $s, int $e ) {
# these are so the block lambda works properly
# (works around what I think is a bug)
my int $ = $s;
my int $ = $e;
start {
my int $acc = 0;
loop ( my int $x = $s; $x < $e; $x += 2) {
next unless (my $s = ~$x) eq $s.flip;
next unless $x.base(2) eq $x.base(2).flip;
$acc += $x;
}
$total ⚛+= $acc;
}
}
my int $cores = (Kernel.cpu-cores * 2.2).Int;
my int $per = 1_000_000 div $cores;
++$per if $per * $cores < 1_000_000;
my #promises;
my int $start = 1;
for ^$cores {
my int $end = $start + $per - 2;
$end = 1_000_000 if $end > 1_000_000;
push #promises, process $start, $end;
#say $start, "\t", $end;
$start = $end + 2;
}
await #promises;
say $total;
Which runs in about 0.63 seconds.
(I messed with the 2.2 value to find a near minimum time on my computer.)

How do I return from an anonymous recursive sub in perl6?

This does what I'd expect. fib(13) returns 233.
sub fib(Int $a --> Int) {
return 0 if $a == 0;
return 1 if $a == 1;
return fib($a -1) + fib($a -2);
}
my $square = -> $x { $x * 2 }; # this works with no return value
my #list = <1 2 3 4 5 6 7 8 9>.map( $square );
# returns [2 4 6 8 10 12 14 16 18]
I tried implementing fib() using an anonymous sub
my $fib = -> Int $x --> Int {
return 0 if $x == 0;
return 1 if $x == 1;
return $fib($x - 1) + $fib($x - 2);
}
$fib(13)
I get the following error when running that with explicit returns.
Attempt to return outside of any Routine
in block at test.p6 line 39
So I got rid of the return values.
my $fib = -> Int $x --> Int {
0 if $x == 0;
1 if $x == 1;
$fib($x - 1) + $fib($x - 2);
}
say $fib(13);
This last version never returns. Is there a way to write an anonymous recursive function without return values?
According to the documentation :
Blocks that aren't of type Routine (which is a subclass of Block) are
transparent to return.
sub f() {
say <a b c>.map: { return 42 };
# ^^^^^^ exits &f, not just the block }
The last statement is the implicit return value of the block
So you can try:
my $fib = -> Int $x --> Int {
if ( $x == 0 ) {
0; # <-- Implicit return value
}
elsif ( $x == 1 ) {
1; # <-- Implicit return value
}
else {
$fib($x - 1) + $fib($x - 2); # <-- Implicit return value
}
}
Three more options:
sub
You can write anonymous routines by using sub without a name:
my $fib = sub (Int $x --> Int) {
return 0 if $x == 0;
return 1 if $x == 1;
return $fib($x - 1) + $fib($x - 2);
}
say $fib(13); # 233
See #HåkonHægland's answer for why this (deliberately) doesn't work with non-routine blocks.
leave
The design anticipated your question:
my $fib = -> Int $x --> Int {
leave 0 if $x == 0;
leave 1 if $x == 1;
leave $fib($x - 1) + $fib($x - 2);
}
compiles. Hopefully you can guess that what it does -- or rather is supposed to do -- is exactly what you wanted to do.
Unfortunately, if you follow the above with:
say $fib(13);
You get a run-time error "leave not yet implemented".
My guess is that this'll get implemented some time in the next few years and the "Attempt to return outside of any Routine" error message will then mention leave. But implementing it has very low priority because it's easy to write sub as above, or write code as #HåkonHægland did, or use a case/switch statement construct as follows, and that's plenty good enough for now.
case/switch (when/default)
You can specify the parameter as $_ instead of $x and then you're all set to use constructs that refer to the topic:
my $fib = -> Int $_ --> Int {
when 0 { 0 }
when 1 { 1 }
$fib($_ - 1) + $fib($_ - 2)
}
say $fib(13); # 233
See when.
Blocks don't need to declare the return type. You can still return whatever you want, though. The problem is not in using return, it's in the declaration of the Int.
use v6;
my $fib = -> Int $x {
if $x == 0 {
0;
} elsif $x == 1 {
1;
} else {
$fib($x - 1) + $fib($x - 2);
}
}
say $fib(13) ;
The problem is that the return value needs to be the last executed. In the way you have done it, if it finds 0 or 1 it keeps running, getting to the last statement, when it will start all over again.
Alternatively, you can use given instead of the cascaded ifs. As long as whatever it returns is the last issued, it's OK.

Time/Space-Complexity method

I got a question to answer with the best complexity we can think about.
We got one sorted array (int) and X value. All we need to do is to find how many places in the array equals the X value.
This is my solution to this situation, as i don't know much about complexity.
All i know is that better methods are without for loops :X
class Question
{
public static int mount (int [] a, int x)
{
int first=0, last=a.length-1, count=0, pointer=0;
boolean found=false, finish=false;
if (x < a[0] || x > a[a.length-1])
return 0;
while (! found) **//Searching any place in the array that equals to x value;**
{
if ( a[(first+last)/2] > x)
last = (first+last)/2;
else if ( a[(first+last)/2] < x)
first = (first+last)/2;
else
{
pointer = (first+last)/2;
count = 1;
found = true; break;
}
if (Math.abs(last-first) == 1)
{
if (a[first] == x)
{
pointer = first;
count = 1;
found = true;
}
else if (a[last] == x)
{
pointer = last;
count = 1;
found = true;
}
else
return 0;
}
if (first == last)
{
if (a[first] == x)
{
pointer = first;
count = 1;
found = true;
}
else
return 0;
}
}
int backPointer=pointer, forwardPointer=pointer;
boolean stop1=false, stop2= false;
while (!finish) **//Counting the number of places the X value is near our pointer.**
{
if (backPointer-1 >= 0)
if (a[backPointer-1] == x)
{
count++;
backPointer--;
}
else
stop1 = true;
if (forwardPointer+1 <= a.length-1)
if (a[forwardPointer+1] == x)
{
count++;
forwardPointer++;
}
else
stop2 = true;
if (stop1 && stop2)
finish=true;
}
return count;
}
public static void main (String [] args)
{
int [] a = {-25,0,5,11,11,99};
System.out.println(mount(a, 11));
}
}
The print command count it right and prints "2".
I just want to know if anyone can think about better complexity for this method.
Moreover, how can i know what is the time/space-complexity of the method?
All i know about time/space-complexity is that for loop is O(n). I don't know how to calculate my method complexity.
Thank a lot!
Editing:
This is the second while loop after changing:
while (!stop1 || !stop2) //Counting the number of places the X value is near our pointer.
{
if (!stop1)
{
if ( a[last] == x )
{
stop1 = true;
count += (last-pointer);
}
else if ( a[(last+forwardPointer)/2] == x )
{
if (last-forwardPointer == 1)
{
stop1 = true;
count += (forwardPointer-pointer);
}
else
forwardPointer = (last + forwardPointer) / 2;
}
else
last = ((last + forwardPointer) / 2) - 1;
}
if (!stop2)
{
if (a[first] == x)
{
stop2 = true;
count += (pointer - first);
}
else if ( a[(first+backPointer)/2] == x )
{
if (backPointer - first == 1)
{
stop2 = true;
count += (pointer-backPointer);
}
else
backPointer = (first + backPointer) / 2;
}
else
first = ((first + backPointer) / 2) + 1;
}
}
What do you think about the changing? I think it would change the time complexity to O(long(n)).
First let's examine your code:
The code could be heavily refactored and cleaned (which would also result in more efficient implementation, yet without improving time or space complexity), but the algorithm itself is pretty good.
What it does is use standard binary search to find an item with the required value, then scans to the back and to the front to find all other occurrences of the value.
In terms of time complexity, the algorithm is O(N). The worst case is when the entire array is the same value and you end up iterating all of it in the 2nd phase (the binary search will only take 1 iteration). Space complexity is O(1). The memory usage (space) is unaffected by growth in input size.
You could improve the worst case time complexity if you keep using binary search on the 2 sub-arrays (back & front) and increase the "match range" logarithmically this way. The time complexity will become O(log(N)). Space complexity will remain O(1) for the same reason as before.
However, the average complexity for a real-world scenario (where the array contains various values) would be very close and might even lean towards your own version.