How can I use square brackets in perl like C? - perl

Yesterday Computerphile uploaded a video about code golf and bitshift variations and I was really fascinated of the program generating music.
This is my formatted version of the code in the video.
int g(int sample, int x, int t, int overdrive) {
return (
(
3 & x & (
sample *
(
(
3 & sample >> 16
?
"BY}6YB6%"
:
"Qj}6jQ6%"
)[t % 8]
+
51
) >> overdrive
)
) << 4
);
}
int main(int n, int s) {
for (int sample=0 ;; sample++)
putchar(
g(sample, 1, n=sample >> 14, 12)
+
g(sample, s=sample >> 17, n^sample >> 13, 10)
+
g(sample, s/3, n + ((sample >> 11) % 3), 10)
+
g(sample, s/5, 8 + n-((sample >> 10) % 3), 9)
);
}
I wanted to try convert the program to pure perl and this is my attempt.
sub g {
return (
(
3 & $_[1] & (
$_[0] *
(
(
3 & $_[0] >> 16
?
"BY}6YB6%"
:
"Qj}6jQ6%"
)[$_[2] % 8]
+
51
) >> $_[3]
)
) << 4
);
}
for($i=0;;$i++){
print pack('C',
g($i, 1, $n=$i >> 14, 12)
+
g($i, $s=$i >> 17, $n^$i >> 13, 10)
+
g($i, $s/3, $n + (($i >> 11) % 3), 10)
+
g($i, $s/5, 8 + $n-(($i >> 10) % 3), 9)
);
}
According to the manual for putchar the the value is internally converted to an unsigned char when written. So I used the pack function in perl with C template which is an unsigned char. However when I pipe the result of both programs to aplay they don't produce the same music.
If I use inline C and call the function g from perl it does work correctly.
use Inline C => <<'END_C';
int g(int sample, int x, int t, int overdrive) {
return (
(
3 & x & (
sample *
(
(
3 & sample >> 16
?
"BY}6YB6%"
:
"Qj}6jQ6%"
)[t % 8]
+
51
) >> overdrive
)
) << 4
);
}
END_C
for($i=0;;$i++){
print pack('C',
g($i, 1, $n=$i >> 14, 12)
+
g($i, $s=$i >> 17, $n^$i >> 13, 10)
+
g($i, $s/3, $n + (($i >> 11) % 3), 10)
+
g($i, $s/5, 8 + $n-(($i >> 10) % 3), 9)
);
}
The only explanation I have is that [$_[2] % 8] is not doing what I think it is in perl.
How can I make the programs produce the same music in perl and C? On windows you can use perl theprogram.pl | sox -c 1 -b 8 -e unsigned -t raw -r 8k - -t waveaudio 0 if you have sox installed.

String is not an array in perl, you need to replace array access with call to substr() function:
...
ord(substr((
3 & $_[0] >> 16
?
"BY}6YB6%"
:
"Qj}6jQ6%"
), $_[2] % 8, 1))
...
More efficient:
# Outside the sub.
my $a1 = [ unpack 'C*', "BY}6YB6%" ];
my $a2 = [ unpack 'C*', "Qj}6jQ6%" ];
...
${ 3 & $_[0] >> 16 ? $a1 : $a2 }[ $_[2] % 8 ]
...

Related

In Raku, how does one calculate the sum of positive divisors from a prime factorization?

In Raku, given a list of pairs (2 => 3, 3 => 2, 5 => 1, 7 => 4) ( representing the prime factorization of n = 2 3 · 3 2 · 5 1 · 7 4 ), how does construct a Raku expression for σ(n) = ( 2 0 + 2 1 + 2 2 + 2 3 ) · ( 3 0 + 3 1 + 3 2 ) · ( 5 0 + 5 1 ) · ( 7 0 + 7 1 + 7 2 + 7 3 + 7 4 ) ?
sub MAIN()
{
my $pairList = (2 => 3, 3 => 2, 5 => 1, 7 => 4) ;
say '$pairList' ;
say $pairList ;
say $pairList.WHAT ;
# Goal:
# from $pairList,
# the product (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
# = sigma ( 2^3 * 3^2 * 5^1 * 7^4 )
} # end sub MAIN
Update 1
Based upon the answer of #raiph, the following program breaks the overall process into stages for the newcomer to Raku (such as me) …
sub MAIN()
{
my $pairList = (2 => 3, 3 => 2, 5 => 1, 7 => 4) ;
say '$pairList' ;
say $pairList ;
say $pairList.WHAT ;
# Goal:
# from $pairList,
# the product (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
# the product (15) * (13) * (6) * (2801)
# sigma ( 2^3 * 3^2 * 5^1 * 7^4 )
# 3277170
# Stage 1 : ((1 2 4 8) (1 3 9) (1 5) (1 7 49 343 2401))
my $stage1 = $pairList.map: { (.key ** (my $++)) xx (.value + 1) } ;
say '$stage1 : lists of powers' ;
say $stage1 ;
say $stage1.WHAT ;
# Stage 2 : ((1 + 2 + 4 + 8) (1 + 3 + 9) (1 + 5) (1 + 7 + 49 + 343 + 2401))
my $stage2 = $stage1.map: { sum $_ } ;
say '$stage2 : sum each list' ;
say $stage2 ;
say $stage2.WHAT ;
# Stage 3 : (1 + 2 + 4 + 8) * (1 + 3 + 9) * (1 + 5) * (1 + 7 + 49 + 343 + 2401)
my $stage3 = $stage2.reduce( &infix:<*> ) ;
say '$stage3 : product of list elements' ;
say $stage3 ;
say $stage3.WHAT ;
} # end sub MAIN
A related post appears on Mathematics Stack Exchange.
Update 2
My original motivation had been to calculate aliquot sum s(n) = σ(n) - n. I found that prime factorization of each n is not necessary and seems inefficient. Raku and C++ programs calculating s(n) for n = 0 … 10 6 follow …
Raku
sub MAIN()
{
constant $limit = 1_000_000 ;
my #s of Int = ( 1 xx ($limit + 1) ) ;
#s[0] = 0 ;
#s[1] = 0 ;
loop ( my $column = 2; $column <= ($limit + 1) div 2; $column++ )
{
loop ( my $row = (2 * $column); $row <= $limit; $row += $column )
{
#s[$row] += $column ;
} # end loop $row
} # end loop $column
say "s(", $limit, ") = ", #s[$limit] ; # s(1000000) = 1480437
} # end sub MAIN
C++
(Observed to execute significantly faster than Raku)
#include <iostream>
#include <vector>
using namespace std ;
int main ( void )
{
const int LIMIT = 1000000 ;
vector<int> s ( (LIMIT + 1), 1 ) ;
s[0] = 0 ;
s[1] = 0 ;
for ( int col = 2 ; col <= (LIMIT + 1) / 2 ; col++ )
for ( int row = (2 * col) ; row <= LIMIT ; row += col )
s[row] += col ;
cout << "s(" << LIMIT << ") = " << s[LIMIT] << endl ; // s(1000000) = 1480437
} // end function main
There'll be bazillions of ways. I've ignored algorithmic efficiency. The first thing I wrote:
say [*] (2 => 3, 3 => 2, 5 => 1, 7 => 4) .map: { sum .key ** my $++ xx .value + 1 }
displays:
3277170
Explanation
1 say
2 [*] # `[op]` is a reduction. `[*] 6, 8, 9` is `432`.
3 (2 => 3, 3 => 2, 5 => 1, 7 => 4)
4 .map:
5 {
6 sum
7 .key # `.key` of `2 => 3` is `2`.
8 **
9 my # `my` resets `$` for each call of enclosing `{...}`
10 $++ # `$++` integer increments from `0` per thunk evaluation.
11 xx # `L xx R` forms list from `L` thunk evaluated `R` times
12 .value + 1
13 }
It is unlikely that Raku is ever going to be faster than C++ for that kind of operation. It is still early in its life and there are lots of optimizations to be gained, but raw processing speed is not where it shines.
If you are trying to find the aliquot sum for all of the numbers in a continuous range then prime factorization is certainly less efficient than the method you arrived at. Sort of an inverse Sieve of Eratosthenes. There are a few things you could change to make it faster, though still probably much slower than C++
About twice as fast on my system:
constant $limit = 1_000_000;
my #s = 0,0;
#s.append: 1 xx $limit;
(2 .. $limit/2).race.map: -> $column {
loop ( my $row = (2 * $column); $row <= $limit; $row += $column ) {
#s[$row] += $column ;
}
}
say "s(", $limit, ") = ", #s[$limit] ; # s(1000000) = 1480437
Where the prime factorization method really shines is for finding arbitrary aliquot sums.
This produces an answer in fractions of a second when the inverse sieve would likely take hours. Using the Prime::Factor module: from the Raku ecosystem
use Prime::Factor;
say "s(", 2**97-1, ") = ", (2**97-1).&proper-divisors.sum;
# s(158456325028528675187087900671) = 13842607235828485645777841

Unable to decode weight machine value when bluetooth weight scale in KG mode in flutter

My weight scale has two modes:
when the device is in-lb(pound mode) the decode output response is correct
DEVICE OUTPUT :[3, 52, 18, 224, 7, 2, 25, 3, 49, 28]
EXPECTED VALUE: 46.6lb
ACTUAL VALUE : 46.6lb
When DEVICE IS IN LB MODE the output is CORRECT using below code
double getWeight(List<int> data, index) {. return (( 0xff & data[index + 1] ) << 8 | ( 0xff & data[index] ) << 0 ) / 100; }
Refer below link for the above code details:
Flutter ble read weight scale characteristic value
But When the device unit is KG MODE, the decode output response is wrong
DEVICE OUTPUT :[2, 168, 12, 224, 7, 2, 25, 3, 51, 7]
EXPECTED VALUE: 46.7 lb
MY DECODED VALUE:32.4 lb
Consume please guide to decode it proper way for this issue?
If you look for "3.244 Weight Scale Measurement" in the following document:
https://www.bluetooth.com/specifications/specs/gatt-specification-supplement-6/
It says about the weight field:
This field is in kilograms with resolution 0.005 if the bit 0 of the
Flag field is 0 or in pounds with a resolution of
0.01 if the bit 0 of the Flag field is 1.
So if the flag suggests you are in KG then you function is:
double getKgWeight(List<int> data, index) {
return (( 0xff & data[index + 1] ) << 8 | ( 0xff & data[index] ) << 0 ) * 0.005;
}
For lbs:
double getlbsWeight(List<int> data, index) {
return (( 0xff & data[index + 1] ) << 8 | ( 0xff & data[index] ) << 0 ) * 0.01;
}

Escaping commas in macro output

I am trying to write a macro which enables me to transform
(a, b, c, d) to (a, a + b, a + b + c, a + b + c + d), etc. Here is what I have got so far:
macro_rules! pascal_next {
($x: expr) => ($x);
($x: expr, $y: expr) => (
($x, $x + $y)
);
($x: expr, $y: expr, $($rest: expr),+) => (
($x, pascal_next!(
$x + $y, $($rest),+
)
)
);
}
However, there is a problem that it would actually output (a, (a + b, (a + b + c, a + b + c +d))). The origin is that the second matching rule ($x: expr, $y: expr) => (($x, $x + $y));, produces an extra bracket, so that there would be nested brackets. If I don't put a bracket outside, I would get the error error:
unexpected token: ,
So is it possible to output a comma , in Rust macros?
No; the result of a macro must be a complete grammar construct like an expression or an item. You absolutely cannot have random bits of syntax like a comma or a closing brace.
You can get around this by simply not outputting anything until you have a complete, final expression. Behold!
#![feature(trace_macros)]
macro_rules! pascal_impl {
/*
The input to this macro takes the following form:
```ignore
(
// The current output accumulator.
($($out:tt)*);
// The current additive prefix.
$prefix:expr;
// The remaining, comma-terminated elements.
...
)
```
*/
/*
Termination condition: there is no input left. As
such, dump the output.
*/
(
$out:expr;
$_prefix:expr;
) => {
$out
};
/*
Otherwise, we have more to scrape!
*/
(
($($out:tt)*);
$prefix:expr;
$e:expr, $($rest:tt)*
) => {
pascal_impl!(
($($out)* $prefix+$e,);
$prefix+$e;
$($rest)*
)
};
}
macro_rules! pascal {
($($es:expr),+) => { pascal_impl!((); 0; $($es),+,) };
}
trace_macros!(true);
fn main() {
println!("{:?}", pascal!(1, 2, 3, 4));
}
Note: To use this on a stable compiler, you will need to delete the #![feature(trace_macros)] and trace_macros!(true); lines. Everything else should be fine.
What this does is it recursively munches away at the input, passing the partial (and potentially semantically invalid) output as input to the next level of recursion. This lets us build up an "open list", which we couldn't otherwise do.
Then, once we're out of input, we just re-interpret our partial output as a complete expression and... done.
The reason I including the tracing stuff is so I could show you what it looks like as it runs:
pascal! { 1 , 2 , 3 , 4 }
pascal_impl! { ( ) ; 0 ; 1 , 2 , 3 , 4 , }
pascal_impl! { ( 0 + 1 , ) ; 0 + 1 ; 2 , 3 , 4 , }
pascal_impl! { ( 0 + 1 , 0 + 1 + 2 , ) ; 0 + 1 + 2 ; 3 , 4 , }
pascal_impl! { ( 0 + 1 , 0 + 1 + 2 , 0 + 1 + 2 + 3 , ) ; 0 + 1 + 2 + 3 ; 4 , }
pascal_impl! { ( 0 + 1 , 0 + 1 + 2 , 0 + 1 + 2 + 3 , 0 + 1 + 2 + 3 + 4 , ) ; 0 + 1 + 2 + 3 + 4 ; }
And the output is:
(1, 3, 6, 10)
One thing to be aware of: large numbers of un-annotated integer literals can cause a dramatic increase in compile times. If this happens, you can solve it by simply annotating all of your integer literals (like 1i32).

Powershell is there an easy way to covert an int 5 to a string five or 68 to sixty eight?

I'm trying to figure out if there is an easy way to convert numbers into words take 9 and convert it to nine.
There is an excellent library for .NET called Humanizer that can do exactly this. I haven't tried this yet, but it looks like there is a PowerShell wrapper for it. I suspect this will do exactly what you need.
This has been asked about .NET/C#; you could put this in a class and use Add-Type in powershell to make this work.
.NET convert number to string representation (1 to one, 2 to two, etc...)
Maybe something like this (untested):
$class = #"
public class Num2Word
{
public static string NumberToText( int n)
{
if ( n < 0 )
return "Minus " + NumberToText(-n);
else if ( n == 0 )
return "";
else if ( n <= 19 )
return new string[] {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
"Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
"Seventeen", "Eighteen", "Nineteen"}[n-1] + " ";
else if ( n <= 99 )
return new string[] {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy",
"Eighty", "Ninety"}[n / 10 - 2] + " " + NumberToText(n % 10);
else if ( n <= 199 )
return "One Hundred " + NumberToText(n % 100);
else if ( n <= 999 )
return NumberToText(n / 100) + "Hundreds " + NumberToText(n % 100);
else if ( n <= 1999 )
return "One Thousand " + NumberToText(n % 1000);
else if ( n <= 999999 )
return NumberToText(n / 1000) + "Thousands " + NumberToText(n % 1000);
else if ( n <= 1999999 )
return "One Million " + NumberToText(n % 1000000);
else if ( n <= 999999999)
return NumberToText(n / 1000000) + "Millions " + NumberToText(n % 1000000);
else if ( n <= 1999999999 )
return "One Billion " + NumberToText(n % 1000000000);
else
return NumberToText(n / 1000000000) + "Billions " + NumberToText(n % 1000000000);
}
}
#"
Add-Type -TypeDefinition $class
[Num2Word]::NumberToText(555)
There's no reason you couldn't write this as pure powershell, but this was already written!

Branch and bound using Perl

I have a problem, I cannot find an answer to. I am using Perl. My input is a symmetric cost-matrix, kind of like the TSP.
I want to know all solutions that lie beneath my boundary, which is 10.
This is my matrix:
- B E G I K L P S
B - 10 10 2 10 10 10 10
E 10 - 2 10 10 10 1 10
G 10 2 - 10 2 3 3 3
I 2 10 10 - 4 10 10 2
K 10 10 2 4 - 10 10 3
L 10 10 3 10 10 - 2 2
P 10 1 3 10 10 2 - 10
S 10 10 3 2 3 2 10 -
Does anybody know how to implement the branch and bound algorithm to solve this? For now, I did replace every 10 in the matrix with "-".
What I did so far:
#verwbez = ( ["-", B, E, G, I, K, L, P, S],
[B,"-", 10, 10, 2, 10, 10, 10, 10],
[E, 10, "-", 2, 10, 10, 10, 1, 10],
[G, 10, 2, "-", 10, 2, 3, 3, 3],
[I, 2, 10, 10, "-", 4, 10, 10, 2],
[K, 10, 10, 2, 4, "-", 10, 10, 3],
[L, 10, 10, 3, 10, 10, "-", 2, 2],
[P, 10, 1, 3, 10, 10, 2, "-", 10],
[S, 10, 10, 3, 2, 3, 2, 10, "-"]);
for ($i=0;$i<=$#verwbez;$i++) {
for ($j=0; $j<=$#{$verwbez[$i]};$j++) {
while ($verwbez[$i][$j] >=7) {
$verwbez[$i][$j] = "-";
}
}
}
Basically just altering the matrix, every 10 is replaced with a "-". Now I want to find all solutions that are beneath 10 and contain 4 districts where always two cities are linked together. But unfortunately, I do not know how to proceed/start...
You're unlikely to get someone to implement the Branch and Bound algorithm for you. However, the following stackoverflow post, TSP - branch and bound, has some links to some helpful resources:
Optimal Solution for TSP using Branch and Bound
B&B Implementations for the TSP -
Part 1: A solution with nodes containing partial tours with
constraints
B&B Implementations for the TSP - Part 2: Single threaded solution with many inexpensive nodes
Since you appear new to perl, we can give you some quick tips
Always include use strict; and use warnings at the top of each and every perl script
Use the range operator .. when creating an incrementing for loop.
Your while loop should actually be an if statement.
For increased style, consider using qw() when initializing a mixed word/number array, especially since it will allow you to easily align a multidimensional array's elements
Your first goal for a project like this should be to create a method to output your multidimensional array in a readable format, so you can observe and verify the changes that you're making.
All of that gives the following changes:
use strict;
use warnings;
my #verwbez = (
[qw(- B E G I K L P S )],
[qw(B - 10 10 2 10 10 10 10)],
[qw(E 10 - 2 10 10 10 1 10)],
[qw(G 10 2 - 10 2 3 3 3 )],
[qw(I 2 10 10 - 4 10 10 2 )],
[qw(K 10 10 2 4 - 10 10 3 )],
[qw(L 10 10 3 10 10 - 2 2 )],
[qw(P 10 1 3 10 10 2 - 10)],
[qw(S 10 10 3 2 3 2 10 - )],
);
for my $i (0 .. $#verwbez) {
for my $j (0 .. $#{$verwbez[$i]}) {
if ($verwbez[$i][$j] =~ /\d/ && $verwbez[$i][$j] >= 7) {
$verwbez[$i][$j] = ".";
}
}
}
for (#verwbez) {
for (#$_) {
printf "%2s ", $_;
}
print "\n";
}
Outputs:
- B E G I K L P S
B - . . 2 . . . .
E . - 2 . . . 1 .
G . 2 - . 2 3 3 3
I 2 . . - 4 . . 2
K . . 2 4 - . . 3
L . . 3 . . - 2 2
P . 1 3 . . 2 - .
S . . 3 2 3 2 . -
Note that B has only 1 city it's near to. So if the goal was solving the TSP, then there isn't a trivial solution. However, given there are only 8 cities and (n-1)! circular permutations. That gives us just 5,040 permutations, so using brute force would totally work for finding a lowest cost solution.
use strict;
use warnings;
use Algorithm::Combinatorics qw(circular_permutations);
my #verwbez = ( ... already defined ... );
# Create a cost between two cities hash:
my %cost;
for my $i (1..$#verwbez) {
for my $j (1..$#{$verwbez[$i]}) {
$cost{ $verwbez[$i][0] }{ $verwbez[0][$j] } = $verwbez[$i][$j] if $i != $j;
}
}
# Determine all Routes and their cost (sorted)
my #cities = keys %cost;
my #perms = circular_permutations(\#cities);
my #cost_with_perm = sort {$a->[0] <=> $b->[0]} map {
my $perm = $_;
my $prev = $perm->[-1];
my $cost = 0;
for (#$perm) {
$cost += $cost{$_}{$prev};
$prev = $_
}
[$cost, $perm]
} #perms;
# Print out lowest cost routes:
print "Lowest cost is: " . $cost_with_perm[0][0] . "\n";
for (#cost_with_perm) {
last if $_->[0] > $cost_with_perm[0][0];
print join(' ', #{$_->[1]}), "\n";
}
It ends up there are only 2 lowest cost solutions to this setup, and they're mirror images of each other, which makes sense since we didn't filter by direction in our circular permutations. Am intentionally not stating what they are here.