Re: Challenge - Creative Way To Detect Alpha Characters
by qumsieh (Scribe) on Sep 13, 2004 at 17:59 UTC
|
This is definitely not creative, and I might be cheating:
if ($foo =~ tr/a-zA-Z//) {
Strictly speaking, tr/// does not use regexps.
;-)
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by CombatSquirrel (Hermit) on Sep 13, 2004 at 18:07 UTC
|
#!perl
use strict;
use warnings;
sub contains_alpha($) {
my ($ord_a, $ord_z, $ord_A, $ord_Z) = map ord, qw/a z A Z/;
for (split //, $_[0]) {
$_ = ord $_;
return 1
if ($ord_a <= $_ and $_ <= $ord_z) || ($ord_A <= $_ and $_ <=
+ $ord_Z);
}
return 0;
}
for (<DATA>) {
chomp;
print "'$_' " . (contains_alpha $_ ? 'contains' : 'does not contain
+')
. " standard alphabet characters\n";
}
__DATA__
Hi
123456789o
1234567890
xAFCE3
xAFCEA
... --- ...
.s. -o- .s.
Not really creative, though...
CombatSquirrel.
Entropy is the tendency of everything going to hell.
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by tye (Sage) on Sep 13, 2004 at 21:12 UTC
|
length($foo)-grep(1+index(((1e9/.7)^7*13*89)."\_",$_),map chr($_),unpa
+ck"C*",$foo) == length("\Q$foo")-length($foo)
(since split and /./gs use regular expressions)
Replace == with != depending on whether you want what was asked for or something that matches the example code given. (:
| [reply] [d/l] [select] |
Re: Challenge - Creative Way To Detect Alpha Characters
by Pragma (Scribe) on Sep 13, 2004 at 20:10 UTC
|
Admittedly not very efficient:
grep { 0 <= index $str, $_ } a..z, A..Z
I like your lc/uc solution the most. Rather creative. | [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by Pragma (Scribe) on Sep 13, 2004 at 21:34 UTC
|
$H{$_}++ for split '', $str;
if (grep $_, @H{a..z,A..Z}) {
...
}
Or an array slice variation:
$A[ord $_]++ for split '', $str;
if (grep $_, @A[map ord, a..z,A..Z]) {
...
}
Update: or forget the slices (duh):
$H{$_}++ for split '', $str;
if (grep $H{$_}, a..z, A..Z) {
...
}
$A[ord $_]++ for split '', $str;
if (grep $A[ord $_], a..z, A..Z) {
...
}
Update #2: using POSIX:
use POSIX;
if ( grep { isalpha $_ } split '', $str ) {
...
}
Add salt, quotes, and strict to taste. | [reply] [d/l] [select] |
Re: Challenge - Creative Way To Detect Alpha Characters
by amt (Monk) on Sep 13, 2004 at 17:46 UTC
|
| [reply] |
|
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by Fletch (Bishop) on Sep 13, 2004 at 18:07 UTC
|
| [reply] [d/l] |
|
Great minds think alike :)
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by TheEnigma (Pilgrim) on Sep 13, 2004 at 18:12 UTC
|
I'm not sure I understand. Do you want to do something only if there are no alpha characters? Because isn't that whatif ( lc $foo eq uc $foo ) { }
would do?
I just want to make sure I understand the condition of the challenge, not that I'm up to it ;)
TheEnigma | [reply] [d/l] |
|
TheEnigma,
Do you want to do something only if there are no alpha characters
Or the reciprocal - do something only if there are alpha chars. The trick is to figure it out creatively without using regular expressions. As you can see, assuming for a second plain jane ASCII, the only way lc $foo eq uc $foo can be true is if there are no alpha ([a-zA-Z]) characters in $foo.
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by UnderMine (Friar) on Sep 13, 2004 at 22:22 UTC
|
Given that your language is limited and '||' concatanates stings I would guess at SQL.
CASE WHEN LOWER(foo) = UPPER(foo) THEN 'No Alpha' ELSE 'Alpha' END
However in some SQL varients you can use translate (has an effect like tr///)
CASE WHEN INSTR(TRANSLATE(foo,
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'),
'X')>0
THEN 'Alpha' ELSE 'No Alpha' END
Or Even
CASE WHEN LENGTH(TRANSLATE(foo,
'#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'#'))<>LENGTH(foo)
THEN 'Alpha' ELSE 'No Alpha' END
Hope it Helps
UnderMine | [reply] [d/l] [select] |
|
| [reply] |
|
I first thought it could be maple. Maple uses || for string catenation (in version 5 and 7, version 3 uses .).
It does not have regexps.
However, maple (version 7 at least) has string functions to do this:
with(StringTools):
str:="2-h/":
if ""<>Select(IsAlpha, str) then `has alphas` else `no alphas` fi;
str:="2-/":
if ""<>Select(IsAlpha, str) then `has alphas` else `no alphas` fi;
| [reply] [d/l] [select] |
|
/* rexx */
strings.1 = 85865487878
strings.2 = 'oewiopeoewirpo iep '
strings.3 = '4889jfkjdk'
strings.4 = 'hfhjh 767484'
strings.5 = '<&jZ>(){}'
strings.6 = '<&>(){}'
do i = 1 to 6
say has_alpha(strings.i) '-> alpha? ' "'"strings.i"'"
end
exit
has_alpha: procedure
parse upper arg string
if (length(string) = 0 | datatype(string) = 'NUM')
then
return 0
start = c2d( 'A' )
stop = c2d( 'Z' )
do while start <= stop
if ( pos(d2c(start) , string) \= 0 )
then
return 1
start = start +1
end
return 0
...which gives...
0 -> alpha? '85865487878'
1 -> alpha? 'oewiopeoewirpo iep '
1 -> alpha? '4889jfkjdk'
1 -> alpha? 'hfhjh 767484'
1 -> alpha? '<&jZ>(){}'
0 -> alpha? '<&>(){}'
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by parv (Parson) on Sep 13, 2004 at 19:44 UTC
|
It would be hard to suggest a solution w/o knowing the capabilities
of that language. Does it support index() like function? Can it
convert between hex and decimal values? OTOH, would a solution in perl
do?
UPDATE: I decided to give a perl solution anyway. Use
index() in a loop (similar to
CombatSquirrel's reply and possibly slower) ...
sub has_alpha
{ my $string = shift;
return
scalar
map { index($string , $_) == -1 ? () : 1 }
('a' .. 'z' , 'A' .. 'Z') ;
}
| [reply] [d/l] [select] |
|
parv,
Heh - I don't know the language myself except from what code I saw as supplemental information in the very long and boring meeting. I was going for a Perl solution by handi-capping it by not allowing regexes.
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by Pragma (Scribe) on Sep 13, 2004 at 23:59 UTC
|
Iterating is for wussies:
my @ALPHA;
$ALPHA[ord $_]++ for 'a'..'z', 'A'..'Z';
sub hasalpha {
my $str = shift;
return $ALPHA[ord $str] if length $str < 2;
my $pos = int rand length $str;
return hasalpha(substr $str, 0, $pos) || hasalpha(substr $str, $pos)
+;
}
print hasalpha('1231a21221');
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by davido (Cardinal) on Sep 14, 2004 at 05:22 UTC
|
I couldn't help but turn Quantum::Superpositions loose on this problem. The 'any()' function is the key to a creative solution. The idea is to compare the return value of 'any( $test_string )' with the return value of 'any( 'A'..'Z', 'a'..'z' )'. If the comparison results in equality, you've got alphas in your test string. Here's an example:
use strict;
use warnings;
use Quantum::Superpositions;
{
my $superstring = any( 'A'..'Z', 'a'..'z' );
sub has_alpha {
return $superstring eq any(
map chr, unpack 'C*', shift
);
}
}
while ( <DATA> ) {
chomp;
print "$_\t=>\thas alphas.\n" if has_alpha($_);
}
__DATA__
12345
abcdef12345
$@!^%^&(*aB&#@
1A2B3C4D
!@#$*&()
I love that module. theDamian++. Of course if you want to implement this solution in another language, you'll have to port his module too. ;)
Updated: Streamlined the code a bit, and eliminated need for split.
| [reply] [d/l] [select] |
|
Of course, before porting Quantum::Superpositions to another language, you might want to consider porting perl's other nondeterministic embedded domain specific language with the terse syntax that's specifically optimized for operating on strings ;-)
-- All code is 100% tested and functional unless otherwise noted.
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by doowah2004 (Monk) on Sep 13, 2004 at 21:01 UTC
|
I don't know if this will work for all cases, but I was trying to be creative.
foreach (@alpha = split //,$foo) { $_++;
if (($_**2 == 0) && ($_ != 1) ){
print "$foo Contains Alpha Characters\n";
last;
}
}
Cameron | [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by tachyon (Chancellor) on Sep 14, 2004 at 02:11 UTC
|
use Inline "C";
print is_alpha("foo");
__END__
__C__
int is_alpha( char * str )
{
while ( *str != '\0' ) {
if ( ((*str >= 97) && (*str <=122)) || ((*str >= 65) && (*str
+<=90)) )
return 1;
str++;
}
return 0;
}
| [reply] [d/l] |
|
use Inline "C";
print is_alpha("foo");
__END__
__C__
int is_alpha( char * str )
{
while ( *str ) if ( isalpha( *str++ ) ) return 1;
return 0;
}
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by ambrus (Abbot) on Sep 14, 2004 at 07:30 UTC
|
This is both perl-specific and slow, but I'll just show it:
sub isalpha {
no warnings "numeric";
my($p) = @_;
0==++$p;
}
sub hasalpha {
my($s) = @_;
isalpha(substr($s, 0, 1, "")) and return 1 while
length($s);
return;
};
| [reply] [d/l] |
|
You could hit it from the back {g}:
sub hasalpha {
local($_) = @_;
isalpha chop and return 1 while length;
return;
}
| [reply] [d/l] |
|
Shurely shome mishtake. This returns true for anything other than 0-9, doesn't it? Is that what the OP wanted?
My solution, slightly similar to one of the others:
$range[ chop ] = 1 while $_; # $_ is copy :)
grep $_, @range[65..90,97..122];
Did someone mention efficiency (I hope not)? | [reply] [d/l] |
|
No. The isalpha function I gave returns true only for
[a-zA-Z] characters, false on numbers,
punctation, international letters, or any other character.
It seems to give the same results for me
than lc ne uc:
sub isalpha {
no warnings "numeric";
my($p) = @_;
0==++$p;
}
sub hasalpha {
my($s) = @_;
isalpha(substr($s, 0, 1, "")) and return 1 while
length($s);
return;
};
@t = ("f/2", "-2/", "*+)", "165", "foop", " A=");
$\=$/; $,=" ";
print grep hasalpha($_), @t;
print grep lc ne uc, @t;
outputs
f/2 foop A=
f/2 foop A=
This is because if $p is a non-alnum character in the
isalpha function, $p++ converts it to a numeric 0 first,
than it increases it to 1, so 0==$p++ is false.
| [reply] [d/l] [select] |
|
Your forgot to ord before you chop.
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by Anonymous Monk on Sep 13, 2004 at 22:32 UTC
|
Okay, I think this should work:
#!/usr/bin/perl
$string = $ARGV[0];
for(split(//,$string)) {
if(($_ * $_ == 0) && $_ ne '0') {
print "alpha: $string\n";
exit(0);
}
}
print "numeric: $string\n";
jkauffman | [reply] |
|
#!/usr/bin/perl
$string = $ARGV[0];
for(split(//,$string)) {
if(($_ * $_ == 0) && $_ ne '0') {
print "alpha: $string\n";
exit(0);
}
}
print "numeric: $string\n";
jkauffman
| [reply] [d/l] |
|
jkauffman,
Unfortunately this code fails for special chars (@,#,$,%...), if you $_++, the the special chars=>1, but alphas increment. If you look at my code above you will see that our attempts are similar, $_**2 is the same as $_ * $_, and does remove the the numbers (except 0) again this is why you would use $_++, adding that first takes care of the zero. I am just not sure if my code above filters all special chars.
Good attempt, we were thinking similar ;)
Cameron
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by Aristotle (Chancellor) on Sep 15, 2004 at 05:28 UTC
|
sub has_alpha {
local $_ = shift;
my %c;
@c{ unpack "(A1)*", $_ } = ( 1 ) x length;
$_ && return 1 for @c{ 'A'..'Z', 'a'..'z' };
return;
}
Makeshifts last the longest.
| [reply] [d/l] |
Re: Challenge - Creative Way To Detect Alpha Characters
by doowah2004 (Monk) on Sep 14, 2004 at 14:58 UTC
|
After reading posts, I realized my error in using split, so I rewrote and simplified to:
while ($_ = substr($foo,$i++,1)){
if (++$_**2 == 0) {
print "$foo Contains Alpha Characters\n";
last;
}
}
This is better I think.
Cameron
UPDATE: I have updated the code with the suggestions offered by ambrus. Thanks for pointing that out...ambrus I reverted to the original code, and am posting the changes below.
Updated with ambrus suggestions:
my $i = 0;
while (local $_ = substr($foo,$i++,1)){
if (++$_ == 0) {
print "$foo Contains Alpha Characters\n";
last;
}
}
I optimized further:
while (++substr($foo,$i++,1) != 0){}
This breaks at an alpha char, and significantly increases the speed, but it is still ~3 times slower that initial solution.
| [reply] [d/l] [select] |
|
I think this works without the **2 too.
Also, you'll want to add my $i = 0; before and
change while ($_ = to while (local $_ =
(or reorganize it to a for loop that localizes automatically)
if you want to use this more than once.
Update: for the record, the original code
had ++$_**2 instead of ++$_.
| [reply] [d/l] [select] |
Re: Challenge - Creative Way To Detect Alpha Characters
by johndageek (Hermit) on Sep 14, 2004 at 14:51 UTC
|
perl -le '@t=split(/[A-Z]|[a-z]/,"1gGiI234");print "$#t\n";'
Silly question, doesn't uc/lc "walk the string" in the background?
| [reply] [d/l] |
|
johndageek,
Because it has just been for fun, I haven't been too strict on the loose set of rules, but split takes a regular expression as the first argument - which isn't allowed. To answer your question, the string has to be walked in some fashion to change case though special care has to be taken if we aren't talking about plain jane ASCII.
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by parv (Parson) on Sep 14, 2004 at 21:37 UTC
|
To all those, including myself, who are using, or had used, two
lists (a..z , A..Z): Why not just convert the string to
either upper or lower case before working on it so that only
26-element list, instead of 52, would be needed?
In my case ... i didn't even think of it until i was working on the
Rexx solution. To repent, below is perl translation....
sub has_alpha
{ my ($string) = @_;
return unless length $string;
$string = lc $string;
my ($start , $stop) = qw/a z/;
while ($start le $stop)
{ index($string , $start++) != -1 and return 1;
}
return;
}
| [reply] [d/l] [select] |
|
You'd then have to scan the list twice. Once to convert, once to compare.
The original (and best) solution did 3 passes by both upping and lowing the string and comparing, but all three passes where in C rather than perl, so fast.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] [d/l] |
|
(I removed my comment about the first statement of BrowserUK about which i am still thinking.)
Yes, you are quite right, BrowserUK, on the point of original
solution being the best; it is simple, short, and to the point.
| [reply] |
Re: Challenge - Creative Way To Detect Alpha Characters
by premchai21 (Curate) on Sep 15, 2004 at 23:13 UTC
|
Highly ASCII-specific, and inefficient, but perhaps mildly interesting. Appears to work, though no absolute guarantees are made of course. Using tr/// is kind of a wart, though, hmm.
sub contains_alpha
{
use bytes;
my ($string) = @_;
my $len = length($string .= "");
my @b = map{$string & (chr(1<<$_) x $len)} (0..7);
tr/\x01-\xff/\x01/ for @b;
my $result =
(~$b[7]) & ($b[6]) &
(($b[4] & ~($b[3] & (($b[1] & $b[0]) | $b[2])))
| ((~$b[4]) & ($b[3] | $b[2] | $b[1] | $b[0])))
;
$result =~ tr/\x00//d;
length($result);
}
| [reply] [d/l] |