Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

masking string 4

Status
Not open for further replies.

josoers

Programmer
May 13, 2003
17
0
0
NL
i have written the following PHP function that masks a string with ***'s and then unveils 1/3 of its original letters to form a hint:

$length = strlen($answer);
$hint = "";
for ($x=0;$x<$length;$x++){
$hint .= "*";
}
for ($x=0;$x<($length/3);$x++){
$ran = rand(0,$length-1);
$hint[$ran] = $answer[$ran];


Now I need this in perl. I tried this:

$length = length($answer);
$lower=0;
$upper=$length;
$hint = "";
for ($x=0;$x<$length;$x++){
$hint .= "*";
}
for ($x=0;$x<($lengte/3);$x++){
$ran = int(rand( $upper-$lower+1 ) ) + $lower;
substr($hint, $ran, $ran) = substr($antwoord, $ran, $ran);

the masking to **** works but the unveiling doesnt work properly. Now I know nothing about perl so most probably theres an easy and correct way, could someone show me?

thanks
 
hi josoers

i'm sorry i had to go last night - v tired!

i hope you are all sorted now - i notice you cleared up your substr problem (i think that i was a little fuzzy last night and i was not entirely correct in thinking you had made a mistake)

I have taken a look at your new posting:-

Code:
$length = length($answer);
$lower= 0; [red]as this is zero throughout the script there is no need for this[/red]
$upper = $length; [red]i think there is no need for this as it is exactly the same as $length[/red]
$hint = ""; [red]this 'probably' isn't necessary[/red]
for ($x=0;$x<$length;$x++){
$hint .= "*"; [red]this can be simplified[/red]
}
for ($x=0;$x<($length/3);$x++){
$ran = int(rand( $upper-$lower+1 ) ) + $lower; [red]this can be much simpler syntax[/red]
substr($hint, $ran, 1) = substr($answer, $ran, 1);
}

i'm only trying to help - please tell me if you feel i have made any errors in my judgement. by simplifying the script you should be able to understand it much better

this 'should' do the same as your script...

Code:
#!/usr/bin/perl

$answer = "apple";

$hint = "*" x length($answer);

for ($x=0; $x<length($answer)/3; $x++){
  substr($hint, $ran, 1) = substr($answer, int(rand(length($answer))+1), 1);
};


Kind Regards
Duncan
 
hi Duncan,

did you try running your code? I don't beleive it will do what the OP wants it to.
 
Code:
use strict;
use warnings;

my $word = "antidisestablishmentarianism";
my $hint = $word;

for (0..length($word) -1) {
    substr($hint, $_, 1) = '*' if (int(rand(3)));
}

print $hint;
But the results are really variable, due to the rand(). For short words, you could easily get the whole word, or none of it. Kevin's method is better
Code:
use strict;
use warnings;

my $word = "antidisestablishmentarianism";
my $hint = $word;

for (0..length($word) * 2 / 3 - 1) {
    my $i = int(rand(length($word)));
    redo if substr($hint, $i, 1) eq  '*';
    substr($hint, $i, 1) = '*';
}

print $hint;
as it always masks the correct number of letters.
 
Between KevinADC and stevexff I think we have an elegant and reliable solution. Well done guys, one of the few times that I wholeheartedly agree with the use of "substr".

Have stars.


Trojan
 
Hi Kevin

I have made no effort to solve his problem - or to improve his script - just simplify it. I just saw a few things that i thought i could make more legible and send that back

Your script looks great for solving the problem


Kind Regards
Duncan
 
Sorry duncdude, I shouldn't have missed you out so join the merry throng and have a star.


Trojan.
 
Guys,

Got a cheeky idea for you:
Code:
#!/usr/bin/perl -w
use strict;
use diagnostics;
my $word = "antidisestablishmentarianism";
my $hint = $word;
$hint =~ s/(.)/(rand > 0.33 ? "*" : $1)/eg;
print "$word   $hint\n";

It's more akin to stevexff's idea in that the number of stars are not guaranteed but it's basically a one-liner.

Trojan.
 
Code:
[b]#!/usr/bin/perl[/b]

$answer = "antidisestablishmentarianism";

@array = split(//, $answer);

do {
  $array[rand(@array)] = '*';    
} until grep (/\*/, @array) == int((length $answer) / 3);

print @array;


Kind Regards
Duncan
 
Thanks Trojan!

I love the last solution... not for the feint hearted!!!


Kind Regards
Duncan
 
How's about this for another variation:
Code:
substr($hint,rand(length($hint)),1) = "*" while(++$count < length($hint)*.67);
print "$hint\n";
Again, one-liner time!

(substr! Yuk!) :)

Trojan.
 
TIMTOWDTI - another one-liner:
Code:
print join '', map int( rand( 3 ) ) ? '*' : $_, split //, $word;
 
Ishnid,

I like it! :)
I'm always a fan of the one-liners.
Go on, I'm feeling unusually generous today.
Have a star!.


Trojan.
 
ishnid

that is beautiful - but it doesn't work

try running 'apples' through - it should always give you 2 stars


Kind Regards
Duncan
 
I should've stated that it's subject to the same restrictions as stevexff's solution and Trojan's first one, in that the exact number of stars isn't guaranteed. (actually, `apples' should yield 4 stars - 1/3 of the original string should be shown, with 2/3 masked).
 
hi ishnid

sorry - i wasn't intending to be rude as i am quite aware your programming skills are to be reckoned with. And you are quite correct - i've got my maths back-to-front!

Code:
[b]#!/usr/bin/perl[/b]

$answer = "apples";

@array = split(//, $answer);

do {
  $array[rand(@array)] = '*';    
} until grep (/\*/, @array) == int((length $answer) / (3/2));

print @array;


Kind Regards
Duncan
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top