I would like to generate every possible consecutive substring of a string, including the end of the word/beginning from the word (cyclic) letter combinations. I've found an example in Python, but the only language I know is perl (and barely, I'm a beginner). I would appreciate it a lot if someone can help me translating the code to perl or to help me find a solution in perl.
the code is the following:
aa='ABCD'
F=[]
B=[]
for j in range(1,len(aa)+1,1):
for i in range(0,len(aa),1):
A=str.split(((aa*j)[i:i+j]))
B=B+A
C=(B[0:len(aa)*len(aa)-len(aa)+1])
it gives you:
C=['A', 'B', 'C', 'D', 'AB', 'BC', 'CD', 'DA', 'ABC', 'BCD', 'CDA', 'DAB', 'ABCD']`
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $string = 'ABCD';
my #substrings;
for my $length (1 .. length $string) {
for my $pos (0 .. length($string) - 1) {
push #substrings, substr $string x 2, $pos, $length;
}
}
say for #substrings;
If you're interested in using a pre-built solution, you could checkout the CPAN, where I found the module String::Substrings. Because you want "wrap-around" substrings and want to eliminate the "substrings" that have the same length as the actual string, you'll have to do a little manipulation:
#!/usr/bin/perl
use strict;
use warnings;
use String::Substrings;
use feature 'say';
my $string = 'ABCD';
my %substrs;
for my $len (1..length($string)-1) {
$substrs{$_}++ for substrings("$string"x2, $len);
}
say for sort keys %substrs;
Results:
A
AB
ABC
B
BC
BCD
C
CD
CDA
D
DA
DAB
Related
I'm new to perl. I know I can split some constant number of characters via unpack or using regexes.
But is there some standard way to split every n characters and new lines?
Here's the string I'm looking to split:
my $str="hello\nworld";
my $num_split_chars=2;
Perhaps the following will be helpful:
use strict;
use warnings;
use Data::Dumper;
my $str = "hello\nworld";
my $num_split_chars = 2;
$num_split_chars--;
my #arr = $str =~ /.{$num_split_chars}.?/g;
print Dumper \#arr;
Output:
$VAR1 = [
'he',
'll',
'o',
'wo',
'rl',
'd'
];
#!/usr/bin/perl -w
use strict;
my $string = $ARGV[0];
my #caracteresSeparados = split(//,$string);
my $temp;
my #complementoADN;
foreach my $i(#caracteresSeparados){
if($i eq 'a'){
$temp = 't';
push(#complementoADN,$temp);
}elsif($i eq 'c'){
$temp = 'g';
push(#complementoADN,$temp);
}elsif($i eq 'g'){
$temp = 'c';
push(#complementoADN,$temp);
}elsif($i eq 't'){
$temp = 'a';
push(#complementoADN,$temp);
}
}
printf("#complementoADN\n");
I've this code that receive by argument one string with A,C,G,T letters.
My objective with this script is to receive that string that the user just can write these letters above and then should print in console the same letters replaced, i mean
A replace by T
C replace by G
G replace by C
T replace by A
I'm not restricting user to introduce other letters, but it's no problem for now...
One Example:
user introduce argument: ACAACAATGT
Program should print: TGTTGTTACA
My script is doing it right.
My question is, can i do it with Hash Lists? If yes can you show me that script with Hashes working? Thanks a lot :)
It doesn't involve hashes, but if you're looking to simplify your program, look up the tr// ("transliteration") operator. I believe the below will be identical to yours:
#!/usr/bin/perl -w
use strict;
my $string = $ARGV[0];
my $complementoADN = $string;
$complementoADN =~ tr/ACGT/TGCA/;
print $complementoADN, "\n";
IMSoP's answer is correct - in this case, tr is the most appropriate tool for the job.
However, yes, it can also be done with a hash:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
my $original = 'ACAACAATGT';
my $replaced;
my %flip = (
A => 'T',
C => 'G',
G => 'C',
T => 'A',
);
for (split '', $original) {
$replaced .= $flip{$_};
}
say $replaced;
Output:
TGTTGTTACA
I am trying to use List::MoreUtils methods. But, need some clarity on its usage it in some scenarios.
Please let me know, if it can be used with a map. For example:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util;
use List::MoreUtils;
use Data::Dumper;
my #udData1 = qw(WILL SMITH TOMMY LEE JONES);
my #arr = qw(WILL TOMMY);
my %output = map{$_=>List::MoreUtils::firstidx{/$_/} #udData1} #arr;
print Dumper %output;
print List::MoreUtils::firstidx{/TOMMY/} #udData1;
print "\n";
Output:
$VAR1 = 'TOMMY';
$VAR2 = 0;
$VAR3 = 'WILL';
$VAR4 = 0;
2
As observed I am not getting the values correctly when using map, but getting it fine when used in the later command.
I intend to use $_ as an element of #arr. This may be incorrect. So, please suggest me an alternative. Shall i have to use foreach?
The problem is this bit right here:
List::MoreUtils::firstidx{/$_/} #udData1
In this bit of code, you're expecting $_ to be both the pattern taken from #arr and the string taken from #udData1 at the same time. (Remember that firstidx{/TOMMY/} means firstidx{$_ =~ /TOMMY/}, and likewise firstidx{/$_/} means firstidx{$_ =~ /$_/}.)
What actually happens is that $_ is the value from #udData1 (since that's the innermost loop) and you wind up matching that against itself. Because it's a simple alphabetic string, it always matches itself, and firstidx correctly returns 0.
Here's one solution using a temporary lexical variable:
my %output = map{ my $p = $_;
$p => List::MoreUtils::firstidx{/$p/} #udData1 } #arr;
Is there an easy way to print out a Perl array with commas in between each element?
Writing a for loop to do it is pretty easy but not quite elegant....if that makes sense.
Just use join():
# assuming #array is your array:
print join(", ", #array);
You can use Data::Dump:
use Data::Dump qw(dump);
my #a = (1, [2, 3], {4 => 5});
dump(#a);
Produces:
"(1, [2, 3], { 4 => 5 })"
If you're coding for the kind of clarity that would be understood by someone who is just starting out with Perl, the traditional this construct says what it means, with a high degree of clarity and legibility:
$string = join ', ', #array;
print "$string\n";
This construct is documented in perldoc -fjoin.
However, I've always liked how simple $, makes it. The special variable $" is for interpolation, and the special variable $, is for lists. Combine either one with dynamic scope-constraining 'local' to avoid having ripple effects throughout the script:
use 5.012_002;
use strict;
use warnings;
my #array = qw/ 1 2 3 4 5 /;
{
local $" = ', ';
print "#array\n"; # Interpolation.
}
OR with $,:
use feature q(say);
use strict;
use warnings;
my #array = qw/ 1 2 3 4 5 /;
{
local $, = ', ';
say #array; # List
}
The special variables $, and $" are documented in perlvar. The local keyword, and how it can be used to constrain the effects of altering a global punctuation variable's value is probably best described in perlsub.
Enjoy!
Also, you may want to try Data::Dumper. Example:
use Data::Dumper;
# simple procedural interface
print Dumper($foo, $bar);
For inspection/debugging check the Data::Printer module. It is meant to do one thing and one thing only:
display Perl variables and objects on screen, properly formatted (to
be inspected by a human)
Example usage:
use Data::Printer;
p #array; # no need to pass references
The code above might output something like this (with colors!):
[
[0] "a",
[1] "b",
[2] undef,
[3] "c",
]
You can simply print it.
#a = qw(abc def hij);
print "#a";
You will got:
abc def hij
# better than Dumper --you're ready for the WWW....
use JSON::XS;
print encode_json \#some_array
Using Data::Dumper :
use strict;
use Data::Dumper;
my $GRANTstr = 'SELECT, INSERT, UPDATE, DELETE, LOCK TABLES, EXECUTE, TRIGGER';
$GRANTstr =~ s/, /,/g;
my #GRANTs = split /,/ , $GRANTstr;
print Dumper(#GRANTs) . "===\n\n";
print Dumper(\#GRANTs) . "===\n\n";
print Data::Dumper->Dump([\#GRANTs], [qw(GRANTs)]);
Generates three different output styles:
$VAR1 = 'SELECT';
$VAR2 = 'INSERT';
$VAR3 = 'UPDATE';
$VAR4 = 'DELETE';
$VAR5 = 'LOCK TABLES';
$VAR6 = 'EXECUTE';
$VAR7 = 'TRIGGER';
===
$VAR1 = [
'SELECT',
'INSERT',
'UPDATE',
'DELETE',
'LOCK TABLES',
'EXECUTE',
'TRIGGER'
];
===
$GRANTs = [
'SELECT',
'INSERT',
'UPDATE',
'DELETE',
'LOCK TABLES',
'EXECUTE',
'TRIGGER'
];
This might not be what you're looking for, but here's something I did for an assignment:
$" = ", ";
print "#ArrayName\n";
Map can also be used, but sometimes hard to read when you have lots of things going on.
map{ print "element $_\n" } #array;
I've not tried to run below, though. I think this's a tricky way.
map{print $_;} #array;
I am new to programming and hence I am stuck on a basic level problem.
Following is code I wrote for comparison. But the result I get does not make sense to me. I would appreciate if someone could tell me what is going wrong.
There are two arrays: #array1 , #array2 of unequal length.
I wish to compare both and list down values not present in #array1.
my %temp = map {$_,$_}#array2;
for (#array1){
next if exists $temp{$_};
open (FILE, ">>/filename") or die "$!";
print FILE "$_\n";
close(FILE);
}
See the FAQ How do I compute the difference of two arrays? How do I compute the intersection of two arrays?
Adapting the code you posted:
#!/usr/bin/perl
use strict; use warnings;
my #x = 1 .. 10;
my #y = grep { $_ % 2 } #x;
my %lookup = map { $_ => undef } #y;
for my $x ( #x ) {
next if exists $lookup{$x};
print "$x\n";
}
If you're doing this for a test, which I assume you are I would highly suggest is_deeply in the newer versions of Test::More
You'll have to update Test::More
cpanp install Test::More
or if you're on perl 5.5
cpan Test::More
Then you'll have use it
use Test::More;
tests => 1
is_deeply ( \#arr1, \#arr2, 'test failed' );
If you're not doing this for testing, but you're doing this for introspective purposes and the arrays are small, I'd suggest using XXX:
cpanp install http://search.cpan.org/CPAN/authors/id/I/IN/INGY/XXX-0.12.tar.gz
Then you'll have use it
use XXX;
YYY [ \#arr1, \#arr2 ];
That's some pretty clever code you've got there. Your code is more or less identical to what the Perl FAQ says. I might be tempted to do this, however:
my %tmp = map { $_ => 1 } #array2;
my #diff = grep { not exists $tmp{$_} } #array1;
This gets everything in #array1 that's not in #array2, but avoiding all of those out-of-style looping constructs (yay for functional programming). Though what I'd really do is this:
sub comp (\#\#) {
my %t = map { $_ => 1 } #{$_[1]};
return grep { not exists $t{$_} } #{$_[0]};
}
Then you can just do:
my #diff = comp(#array1, #array2); # get items in #array1 not in #array2
#diff = comp(#arraty2, #array1); # vice versa
Or you can go to CPAN. List::Compare::Functional::complement() does what you want, though the syntax is reversed.
Swap #array1 and #array2 in your code?
For simple values like strings or numbers, the following should work
my #result;
my $hosts = [qw(host1 host2 host3 host4 host5)];
my $stie_obj = [qw(host1 host5 host6)];
#result = map { my $a=$_; my $b=grep {/$a/} #$site_obj; $b==0 ? $a : () } #$hosts;
print Dumper (#result);
Should give :
$VAR1 = 'host2';
$VAR2 = 'host3';
$VAR3 = 'host4';