modify this code to print elements that differ a x number from previous position - perl

I wrote this code to find substrings every x elements:
print "enter file path\n";
$letters = <>;
chomp ($letters);
$sequence = "";
open (LETTERS, $letters) or die "error opening\n";
print "how many letters at a shot\n";
$number = <>;
chomp ($number);
$size = length $sequence;
chomp ($size);
for ($i = 0; $i < $size; $i++) {
$test = substr ($sequence, $i, $number);
print "> Test $i\n";
print "$test\n";
if ($i >= $size - $number) {
last;
}
}
so if I open a file with this string and choose x = 3:
abcdefg
I get this result:
> Test 0 abc
> Test 1 bcd
> Test 2 cde
> Test 3 def
> Test 4 efg
Each substring differs from one position from the previous substring, I'd like to be able to control this number and dislocate the substring by 2 for example. So the result would be:
> Test 0 abc
> Test 2 cde
> Test 4 efg
Any suggestions? Thanks

Add:
...
$step = <>;
...
And change:
for ($i = 0; $i < $size; $i++) {
to
for ($i = 0; $i < $size; $i+=$step) {

for ($i = 0; $i < $size; $i += 2) {

Related

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";

Perl Script not running correctly

When ever I run this bit of code. it doesn't display any output. Anyone see anything wrong?
I am trying to display this in the out put:
A
AA
AAA
AAAB
AAABA
AAABAA
AAABAAA
AAABAAAB
etc.
#!/usr/local/bin/perl
$A = 3;
$B = 1;
$i = 1;
$output = "";
$j = 1;
while ($i <= $ARGV[0]) {
while ($j <= $i) {
if ($A == 0 && $B == 0) {
$A = 3;
$B = 1;
}
if ($A > 0) {
$output.= "A";
$A--;
}
else {
$output.= "B";
$B--;
}
$j++;
}
print($output . "\n");
$i++;
}
It works for me when I run it with a numeric argument (number of lines).
An idea how to simplify the code:
#!/usr/bin/perl
use warnings;
use strict;
my $count = shift;
my $A = 3;
my $B = 1;
my $string = q();
$string .= ('A' x $A) . ('B' x $B) while $count > length $string;
print substr($string, 0, $_), "\n" for 1 .. $count;
It uses a different algorithm - it creates the longest possible string, and then outputs parts of it.
if there is no #ARGV, while ($i <= $ARGV[0]) never runs.
#ARGV is an array of the command line arguments provided when the script is executed. you did not provide any command line arguments. if you had use warnings in effect, you would be warned that $ARGV[0] is uninitialized.
As from ikegami comment. You cann't pass the input at when the program is compile. For example, consider your file name is algo.pl. Can you run your program with
perl algo.pl 10
Here 10 is the input value of the program. In program value is retrieve by the $ARGV[0]
so in your program looks like while ($i <= $ARGV[0]).
If you want pass the several values like perl filename.pl 12 data1 data2In your data retrieve by $ARGV[0] $ARGV[1] $ARGV[2] for more information see here.
If you want pass the input at the time of execution used STDIN
use warnings;
use strict;
my $A = 3;
my $B = 1;
my $i = 1;
my $output = "";
my $j = 1;
print "Enter the value: ";
chomp(my $value = <STDIN>);
while ($i <= $value) {
while ($j <= $i) {
if ($A == 0 && $B == 0) {
$A = 3;
$B = 1;
}
if ($A > 0) {
$output.= "A";
$A--;
}
else {
$output.= "B";
$B--;
}
$j++;
}
print($output . "\n");
$i++;
}

Transposing the matrix in perl

I am trying to perform a transpose on a data contained in a file. The data is as follows:
1 2 3 4 5
2 3 4 5 6
4 5 6 7 9
4 3 7 6 9
I am getting the result as follows which is incorrect. I am not getting the error in the code due to which the last column is not transposed properly. Any solution...
Code:
#!/usr/bin/perl
use strict;
use warnings;
my #dependent; # matrix of dependent variable
# Reading the data from text file to the matrix
open( DATA, "<example.txt" ) or die "Couldn't open file , $!"; #depenedent
# Storing data into the array in matrix form
while ( my $linedata = <DATA> ) {
push #dependent, [ split '\t', $linedata ];
}
my $m = #dependent;
#print "$m\n";
my $n = #{ $dependent[1] };
#print $n;
#print "Matrix of dependent variables Y \n";
for ( my $i = 0; $i < $m; $i++ ) {
for ( my $j = 0; $j < $n; $j++ ) {
#print $dependent[$i][$j]," ";
}
#print "\n";
}
my #transpose;
for ( my $i = 0; $i < $n; $i++ ) {
for ( my $j = 0; $j < $m; $j++ ) {
$transpose[$i][$j] = $dependent[$j][$i];
}
}
for ( my $i = 0; $i < $n; $i++ ) {
for ( my $j = 0; $j < $m; $j++ ) {
print $transpose[$i][$j], " ";
}
print "\n";
}
chomp your data when you read it, before you split it; your strange output is caused by the last element of each row of the input still having a newline attached.
Just as a side note, DATA isn't a very good name to pick for a filehandle; perl already defines a special builtin filehandle named DATA for reading data that's embedded in a script or a module, so using that name for yourself can lead to confusion :)

Perl - Trouble With Loop Variables

I'm fairly new to coding in Perl and am used to using C-style for loops. I'm not sure why the following program never prints a value of 4 for $l:
use strict;
use warnings;
my $minL = 4;
for (my $l = $minL; $l > 0; $l--) {
for (my $i = 0; $i + $l < $minL; $i++) {
print "$i $l\n";
}
}
Many thanks in advance.
Your inner for loop has the condition $i + $l < $minL. If $l == $minL, then $i + $l < $minL will be false even if $i is 0, so the loop runs 0 times and never prints anything.
Maybe you wanted to use <= for the condition?
By the way, here is how you could write the same thing (assuming the <= condition) using Perl-style foreach loops:
my $minL = 4;
for my $l (reverse 1 .. $minL) {
for my $i (0 .. $minL - $l) {
print "$i $l\n";
}
}
In the first iteration:
for (my $l = $minL; $l > 0; $l--) {
$l == $minL
for (my $i = 0; $i + $l < $minL; $i++) {
So this block won't run until $l is decremented:
print "$i $l\n";
}
Change your inner loop to:
for (my $i = 0; $i + $l <= $minL; $i++) {

Nested for loop in perl

I'm trying to make a little script with a nested "for" loop in perl.
As I'm learning, at first I've done 3 for loops and it worked well. In order to make something more intelligent, I'd like to nested them but I don't know what is wrong.
If my input text is ABCDEFGHI
I'd like to obtain
text 1 ABC DEF GHI
text 2 BCD EFG HI
text 3 CDE FGH I
But instead of it, my output is
text1 ABC DEF GHI ABC DEF GHI ABC DEF GHI ABC DEF GHI ABC DEF GHI ABC DEF GHI ABC DEF GHI ABC DEF GHI ABC DEF GHI
text2 BCD EFG HI BCD EFG HI BCD EFG HI
text3 CDE FGH I
Here is my script. I'm using perl 5.18.1.
use Modern::Perl '2013';
my #text1;
my #text2;
my #text3;
my $entry = shift;
my $len = length $entry;
for (my $i = 2; $i < $len; $i += 3) {
for (my $i = 1; $i < $len; $i += 3) {
for (my $i = 0; $i < $len; $i += 3) {
my $text = substr($entry, $i, 3);
push #text1, uc($text);
}
my $text = substr($entry, $i, 3);
push #text2, uc($text);
}
my $text = substr($entry, $i, 3);
push #text3, uc($text);
}
say "text1 #text1";
say "text2 #text2";
say "text3 #text3";
I've already taken a look around and here http://perldoc.perl.org/perlsyn.html#For-Loops
Thank you for any help
I don't know why you'd want three nested loops (not counting substr). You only need two: One loop to determine the starting position, and one to walk through the string.
my $text = uc('ABCDEFGHI');
for my $offset (0..2) {
my #parts;
for (my $i=$offset; $i<length($text); $i+=3) {
push #parts, substr($work, $i, 3);
}
say "#parts";
}
Or without substr. to truly demonstrate there are really only two loops:
my $text = uc('ABCDEFGHI');
my #text = split //, $text;
for my $offset (0..2) {
my #parts;
for my $i ($offset..$#text) {
$parts[ ($i - $offset) / 3 ] .= $text[$i];
}
say "#parts";
}
Personally, I'd use
my $text = uc('ABCDEFGHI');
for (1..3) {
my #parts = $text =~ /\G.{1,3}/sg;
say "#parts";
$text =~ s/^.//s;
}
Your three loops do not need to be nested to get your desired output:
use Modern::Perl '2013';
my #text1;
my #text2;
my #text3;
my $entry = shift;
my $len = length $entry;
for (my $i = 0; $i < $len; $i += 3) {
my $text = substr($entry, $i, 3);
push #text1, uc($text);
}
for (my $i = 1; $i < $len; $i += 3) {
my $text = substr($entry, $i, 3);
push #text2, uc($text);
}
for (my $i = 2; $i < $len; $i += 3) {
my $text = substr($entry, $i, 3);
push #text3, uc($text);
}
say "text1 #text1";
say "text2 #text2";
say "text3 #text3";
You could also re-factor this a little, using two nested loops:
use Modern::Perl '2013';
my #texts = ( [], [], [] );
my $entry = shift;
my $len = length $entry;
for ( my $start = 0; $start < 3; $start++ ) {
for ( my $i = $start; $i < $len; $i += 3 ) {
my $text = substr($entry, $i, 3);
push #{$texts[$start]}, uc($text);
}
}
for ( my $start = 0; $start < 3; $start++ ) {
say "text${start} #{$texts[$start]}";
}
As an aside: If you do nest for loops, it will be easier to read and understand your code if you use a different variable as the iterator. The three $i variables you have will work, but I had to check quite a while to make sure that wasn't your problem.