powershell Fibonacci sequence stops early - powershell

when i enter 55 i want the function to print the fibonacci sequence 55 times but the sequence stops at 55
function Get-Fibonacci ($n) {
$current = 0 ;
$previous = 1;
while ($current -lt $n) {
$current;
$current,$previous = ($current+$previous),$current
}
}

function Get-Fibonacci ($n) {
$current = 0 ;
$previous = 1;
for ($i=0; $i -lt $n; $i++) {
$current;
$current,$previous = ($current+$previous),$current
}
}

Here's an answer which doesn't rewrite using a for loop:
function Get-Fibonacci ($n) {
$current = 0 ;
$previous = 1;
$position=0
while ($position -lt $n) {
$position++
'{0} : {1}' -f $position,$current
$current,$previous = ($current+$previous),$current
}
}

Related

Converting C++ to PowerShell

I had an assignment for which I need to list the first 100 Prime Numbers in PowerShell Script. So I coded using C++ and try to convert to PowerShell Script. And the output in PowerShell was not what I am expected.
Note: I am new to PowerShell. Just start learning since past 2 days
I tried to understand the PowerShell syntax and convert it
C++:
int i, j, count = 1, b = 0;
for ( i = 3; i > 0; ++i )
{
for ( j = 2; j <= i / 2; ++j )
{
if ( i % j == 0 )
{
b = 1;
break;
}
}
if ( b == 0 )
{
cout << i << endl;
count++;
}
b = 0;
if ( count == 101 )
break;
}
PowerShell:
$i
$j
$count = 0
$prime = 0
for ( $i = 3; $i -lt 0; ++$i )
{
for ( $j = 2; $j -le $i / 2; ++$j )
{
if ( $i % $j -eq 0 )
{
$prime = 1
break
}
}
if ( $prime -eq 0 )
{
Write-Host("$i 'r 'n")
$count++
}
$prime = 0
if ( $count -eq 101 )
{
break
}
}
I expect the result will be first 100 prime numbers from 3 to 547
But I get 3 2 from PowerShell.
Any advice is welcomed. Thank you in advance
You were close.
> is -gt, you used -lt in your script.
$i = 0
$j = 0
$count = 0
$prime = 0
for ($i = 3; $i -gt 0; ++$i) {
for ($j = 2; $j -le $i / 2; ++$j) {
if ($i % $j -eq 0 ) {
$prime = 1
break
}
}
if ($prime -eq 0) {
Write-Output $i
$count++
}
$prime = 0
if ($count -eq 100) {
break
}
}

Unable to modify array parameter

This is supposed to put the contents of nums into decreasing order, however sort does not change the contents of nums. Many sites I read have said to pass by reference, but I don't think I'm dereferencing the argument correctly. Bear with me, this is my first Perl program :)
#! /usr/bin/env perl
sub sort {
my #arr = #_;
my $len = scalar #arr;
for (my $i = 1; $i < $len-1; $i = $i + 1) {
my $max = $i;
for (my $j = $i + 1; $j < $len; $j = $j + 1) {
if ($arr[$j] > $arr[$max]) {
$max = $j
}
}
$temp = $arr[$max];
$arr[$max] = $arr[$i];
$arr[$i] = $temp;
}
}
print "Enter 10 numbers: ";
my $numbers = <STDIN>;
my #nums = split ' ', $numbers;
print "Unsorted: #nums\n";
sort \#nums;
print "Sorted: #nums\n";
#Matt Jacob helped me out with this one. This is what I was looking for.
#! /usr/bin/env perl
sub selection_sort {
my $arr = shift;
my $len = scalar #$arr;
for (my $i = 0; $i < $len-1; $i++) {
my $max = $i;
for (my $j = $i + 1; $j < $len; $j++) {
if (#$arr[$j] > #$arr[$max]) {
$max = $j
}
}
my $temp = #$arr[$max];
#$arr[$max] = #$arr[$i];
#$arr[$i] = $temp;
}
}
print "Enter 10 numbers: ";
my $input = <STDIN>;
my #integers = split ' ', $input;
print "Unsorted: #integers\n";
selection_sort \#integers;
print "Sorted: #integers\n";

How to make this Perl program print in descending order?

This code works but it prints in ascending order. Do I need to change my whole formula?
print "Enter an integer \n";
my $root = <STDIN>;
my #nums = (100..200);
my $i = 0;
# code in while loop executes as long as condition is true
while ( $i < $#nums )
{
print "$nums[$i]\n",if($nums[$i] % $root == 0); $i++;
}
Just set $i to $#nums instead of 0 and decrement it -- instead of incrementing. You'll need to change the loop condition to $i >= 0 (it should be $i <= $#nums in your code, otherwise it skips 200 when 10 was entered).
#!/usr/bin/perl
use warnings;
use strict;
print "Enter an integer \n";
my $root = <>;
my #nums = (100 .. 200);
my $i = $#nums;
while ( $i >= 0 ) {
print "$nums[$i]\n" if $nums[$i] % $root == 0;
--$i;
}
There are more than a few ways to do it ... not all equally good:
#!/usr/bin/env perl
use strict;
use warnings;
run(#ARGV);
sub run {
my $root = $_[0] // get_root();
my #nums = (100 .. 200);
my #functions = (
sub {
my ($root, $nums) = #_;
my $i = #$nums;
while ($i--) {
print "$nums->[$i]\n" unless $nums->[$i] % $root;
}
return;
},
sub {
my ($root, $nums) = #_;
for my $n ( reverse #$nums ) {
print "$n\n" unless $n % $root;
}
return;
},
sub {
my ($root, $nums) = #_;
my $i;
while ($i++ < #$nums) {
print "$nums->[#$nums - $i]\n" unless $nums->[#$nums - $i] % $root;
}
return;
},
sub {
my ($root, $nums) = #_;
my #multiples = reverse grep !($_ % $root), #$nums;
print "$_\n" for #multiples;
return;
},
);
for my $i ( 0 ... $#functions ) {
print "=== Function $i ===\n";
$functions[$i]->($root, \#nums);
}
}
sub get_root {
return scalar <STDIN>;
}
print "Enter an integer \n";
my $root = <STDIN>;
my #nums = (100..200);
#nums = reverse #nums; #Just reverse the arrays
my $i = 0;
# code in while loop executes as long as condition is true
while ( $i < $#nums )
{
print "$nums[$i]\n",if($nums[$i] % $root == 0); $i++;
}
May be it will helps you.
for (my $i = $#nums; $i >= 0; --$i) { ... }
for (my $i = #nums; $i--; ) { ... }
for my $i (reverse 0 .. $#nums) { ... }
for (1 .. #nums) { my $i = -$_; ... } # Or: my $i = #nums-$_;
for my $num (reverse #nums) { ... }

Powershell: HSL to RGB

I need to convert HSL color values to RGB, or to be more precise HSL-values to a System.Drawing.Color object with Powershell.
There are a few solutions in other prog.-languages out there (like LINK). But while it looks simple, I dont get it converted it into Powershell.
Function HSLtoRGB ($H,$S,$L) {
$H = [double]($H / 360)
$S = [double]($S / 100)
$L = [double]($L / 100)
if ($s -eq 0) {
$r = $g = $b = $l
}
else {
if ($l -lt 0.5){
$q = $l * (1 + $s)
}
else {
$q = $l + $s - $l * $s
}
$p = (2 * $L) - $q
$r = (Hue2rgb $p $q ($h + 1/3))
$g = (Hue2rgb $p $q $h )
$b = (Hue2rgb $p $q ($h - 1/3))
}
$r = [Math]::Round($r * 255)
$g = [Math]::Round($g * 255)
$b = [Math]::Round($b * 255)
return ($r,$g,$b)
}
function Hue2rgb ($p, $q, $t) {
if ($t -lt 0) { $t++ }
if ($t -gt 0) { $t-- }
if ($t -lt 1/6) { return ( $p + ($q + $p) * 6 * $t ) }
if ($t -lt 1/2) { return $q }
if ($t -lt 2/3) { return ($p + ($q - $p) * (2/3 - $t) * 6 ) }
return $p
}
HSLtoRGB 63 45 40 # result should be R 145 G 148 B 56
Let's start with the line you're having trouble with translating:
$q = l < 0.5 ? l * (1 + s) : l + s - l * s; #could not translate this line
This construct:
statement ? someValue : anotherValue;
is known as a ternary operation. It basically means:
if(statement){
someValue
} else {
anotherValue
}
So in PowerShell that becomes:
$q = if($l -lt 0.5){
$l * (1 + $s)
} else {
$l + $s - $l * $s
}
Your translation of the inline Hue2Rgb function has two typos that greatly change the calculation:
function Hue2rgb ($p, $q, $t) {
if ($t -lt 0) { $t++ }
if ($t -gt 0) { $t-- } # This condition should be ($t -gt 1)
if ($t -lt 1/6) { return ( $p + ($q + $p) * 6 * $t ) } # The innermost calculation should be ($q - $p) not ($q + $p)
if ($t -lt 1/2) { return $q }
if ($t -lt 2/3) { return ($p + ($q - $p) * (2/3 - $t) * 6 ) }
return $p
}
Regarding the input values, if you take a look at the comments in the original script:
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
So if you want to pass your input values as degrees (hue) and percentages (saturation + luminance), you'll have to handle a conversion to a relative value between 0 and 1:
Function HSLtoRGB ($H,$S,$L) {
$H = [double]($H / 360)
$S = [double]($S / 100)
$L = [double]($L / 100)
# rest of script
}
Lastly, you can use Color.FromArgb() to return an actual Color object:
$r = [Math]::Round($r * 255)
$g = [Math]::Round($g * 255)
$b = [Math]::Round($b * 255)
return [System.Drawing.Color]:FromArgb($r,$g,$b)

Collatz Conjecture - Iteration rather than Recursion

I am working on something for learning purposes where I have tackled Collatz using recursion. If you see below I make use of #_ and $_ to keep the for alive.
#!/usr/bin/env perl
sub collatz {
my ($num, $count) = #_;
$count++;
if ($num == 1) {
return $count;
} elsif ($num % 2 == 0) {
return collatz($num/2, $count);
} else {
return collatz($num*3 + 1, $count);
}
}
my $max = 0;
my $saved = 0;
for (1..1000) {
my $length = collatz($_, 0);
print "Num: " . $_ . " Length: " . $length . "\n";
if ($length > $max) {
$max = $length;
$saved = $_;
}
}
print "The longest sequence starts with " . $saved . "\n";
I am trying to use iteration instead of recursion but I just can't think of how to tackle this. I am not after the code in the question, I just want some tips / hints on how to tackle this to get the same result.
I suspect I will need to use a while or an until field.
Any help would be appreciated, again I don't want the exact answer.
Update
Here is my second attempt, which is giving me an error of
Can't return outside a subroutine at answer2.pl line 38.
my $number = 0;
my $counter = 0;
while ($number != 1000) {
$counter++;
if ($number == 1) {
return $counter;
}
elsif ($number % 2 == 0) {
return ($number / 2, $counter);
}
else {
return ($number * 3 + 1, $counter);
}
$number++;
}
print "number" . $number . "counter" . $counter . "\n";
Basically you have tail recursion, which is nice and simple to eliminate.
Instead of collatz calling itself to generate the next step in the sequence, you simply change the variables in-place and loop back to the top.
In its crudest form this would be
sub collatz2 {
my ($num, $count) = #_;
NEXT:
$count++;
if ($num == 1) {
return $count;
}
elsif ($num % 2 == 0) {
$num = $num / 2;
}
else {
$num = $num * 3 + 1;
}
goto NEXT;
}
but it should be written much more nicely than that.
I ended up with this
sub collatz {
my ($num) = #_;
my $count = 1;
while ($num > 1) {
$num = $num % 2 ? $num * 3 + 1 : $num / 2;
++$count;
}
$count;
}
Consider adding the logic that returns when the condition is met in the while.
Spoiler:
my $iter = 0;
while($num != 1){ #do stuff; $iter++ }
Just use a for or while loop with the end condition that your number == 1.
Spoiler:
use strict;
use warnings;
my $max_num = 0;
my $max_steps = 0;
for my $num (1..1000) {
my $steps = 0;
for (my $i = $num; $i != 1; $steps++) {
$i = $i % 2 ? 3 * $i + 1 : $i / 2;
}
print "Num: " . $num . " Length: " . $steps . "\n";
if ($steps > $max_steps) {
$max_num = $num;
$max_steps = $steps;
}
}
print "The longest sequence starts with " . $max_num . "\n";