[Challenge] Secret Decoder Ring

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

mischievous
Forum Commoner
Posts: 71
Joined: Sun Apr 19, 2009 8:59 pm

Re: [Challenge] Secret Decoder Ring

Post by mischievous »

Actually I created a script in php for it to work... but haven't had time to tweek it out... seems like for whatever reason my f's wernt coming through and the h's wernt correctly? McInfo, sending the code over to you now... :crazy:
watson516
Forum Contributor
Posts: 198
Joined: Mon Mar 20, 2006 9:19 pm
Location: Hamilton, Ontario

Re: [Challenge] Secret Decoder Ring

Post by watson516 »

The first thing you need to do is create the two patterns based on the first two characters in the string. This could be accomplished a few different ways.
You would then need to loop through the string to be decrypted and find the current letter to be decrypted. If this letter's position is even, you need to find that letter in the first pattern, use that letter's position and then search the second pattern for that same position to give you the actual character. If the current character's position is odd, find the character in the second pattern, use that character's position and then search the first pattern for that same position to give you the actual pattern. These two parts can just be copied and pasted with a few things changed.
Once you figure out the current letter, append that letter to a 'decrypted' variable and when that loop is done, you have the decrypted message. Yay!
mischievous
Forum Commoner
Posts: 71
Joined: Sun Apr 19, 2009 8:59 pm

Re: [Challenge] Secret Decoder Ring

Post by mischievous »

Yeah that's what i did... I put the 1st key and 2nd key into a string variable then split the string into an array did the same with the encoded string and then ran through a for loop alternating between even and odd and outputting my decoded string. :drunk:
User avatar
Weiry
Forum Contributor
Posts: 323
Joined: Wed Sep 09, 2009 5:55 am
Location: Australia

Re: [Challenge] Secret Decoder Ring

Post by Weiry »

Just completed the challenge :D whoot
Image

Edit: i used a rather oldschool method, il post my code after 3rd place is taken. Check your PM's McInfo, i sent you the code i used.

Edit2: now that all medals have been taken, here is my code for decoding:

Code: Select all

$str1 = "string1.txt"; 
        $str1_handle = fopen($str1, "r"); 
        $str1_contents = fread($str1_handle, filesize($str1)); 
        fclose($str1_handle); 
    $str2 = "string2.txt"; 
        $str2_handle = fopen($str2, "r"); 
        $str2_contents = fread($str2_handle, filesize($str2)); 
        fclose($str2_handle); 
    $msg1 = "message2.txt"; 
        $msg1_handle = fopen($msg1, "r"); 
        $msg1_contents = fread($msg1_handle, filesize($msg1)); 
        fclose($msg1_handle); 
        
    $str1Arr = str_split($str1_contents);
    $str2Arr = str_split($str2_contents);
    $msg1Arr = str_split($msg1_contents);
$yabberMessage = array();
for($i=0;$i<count($msg1Arr);$i++){
    if( $i%2 > 0 ){
        $keyBottom = array_search($msg1Arr[$i], $str2Arr,true);
        if($keyBottom){
            array_push($yabberMessage,$str1Arr[$keyBottom]);
        }
    }else{
        $keyTop = array_search($msg1Arr[$i], $str1Arr,true);
        if($keyTop){
            array_push($yabberMessage,$str2Arr[$keyTop]);
        }
    }
}
print $i."<br/>";
print addslashes(implode($yabberMessage))."<br/>";
print implode($str1Arr);
Last edited by Weiry on Fri Sep 11, 2009 10:27 pm, edited 1 time in total.
User avatar
McInfo
DevNet Resident
Posts: 1532
Joined: Wed Apr 01, 2009 1:31 pm

Re: [Challenge] Secret Decoder Ring

Post by McInfo »

Congratulations, Weiry. Now we need just one more winner.

The two solutions I've seen so far are limited to decoding a message that uses "+F" as the first two characters. However, those two characters were randomly chosen during the encoding process. The decoding script should be able to generate the two keys dynamically based on those two characters.

For example, when decoded, this string reveals the same message as the first:

Code: Select all

T:]U)M-G/['G/O*T.f:?*[:N{\ e}X{I&K~e/N e}U~KHecT:U-J X:Z*e+X*\ e/N{Z:_*[:N{\ e.U'\ J:Z#K:V0`5R e2O/N*[/e.V*O'O)M:O/e!U-e \ X4U)K:K'Y q:_*[:S0Y/e~U2T'U{J:G:H{J"K:G)J:G/Z{I#e$Z:O)e{e-K+R4e+U.ZHenN X e{X e/N-K e|G~M Y:m"U'JFe.O'\ XFe{T~e|X*T5KCe/U:H e}R{O(K~e{Z:Z#O.e{J~X Y. :N/Z+ It.T4J \HI*SIuKLJyQGL{~KPJMHP{!~{{O|JL~wN{OyNs::#G)Q.e!U-e+R{_$T"s
Edit: This post was recovered from search engine cache.
Last edited by McInfo on Tue Jun 15, 2010 11:38 am, edited 1 time in total.
SimonMayer
Forum Commoner
Posts: 32
Joined: Wed Sep 09, 2009 6:40 pm

Re: [Challenge] Secret Decoder Ring

Post by SimonMayer »

Image

Hooray, I did it and dynamically too.

Gosh, that took some effort, not to mention a lot of 400 'bad request' and 500 'server errors' on my webhosting, when I tried to use $_POST.

What a lovely challenge. Thank you.
User avatar
McInfo
DevNet Resident
Posts: 1532
Joined: Wed Apr 01, 2009 1:31 pm

Re: [Challenge] Secret Decoder Ring

Post by McInfo »

Party time! :D

Here is the "official" encoder/decoder (Sorry for lack of coments.):

Code: Select all

<?php
class SecretDecoderRing
{
    public static function encode ($message)
    {
        $m = str_split($message, 1);
        do {
            $a = chr(mt_rand(32, 126));
            $b = chr(mt_rand(32, 126));
        } while ($a == $b);
        $k = self::key($a, $b);
        $e = $b.$a;
        foreach ($m as $i => $c) {
            $e .= $k[$i & 1][$c];
        }
        return $e;
    }
    public static function decode ($message)
    {
        $m = str_split($message, 1);
        $a = array_shift($m);
        $b = array_shift($m);
        $k = self::key($a, $b);
        $d = '';
        foreach ($m as $i => $c) {
            $d .= $k[$i & 1][$c];
        }
        return $d;
    }
    private static function key ($a, $b)
    {
        $range = range(chr(32), chr(126));
        $i = array_search($a, $range);
        $x = array_merge(array_slice($range, $i), array_slice($range, 0, $i));
        $j = array_search($b, $range);
        $y = array_merge(array_slice($range, $j), array_slice($range, 0, $j));
        return array
        (   0 => array_combine($x, $y)
        ,   1 => array_combine($y, $x)
        );
    }
}
 
// Example usage:
header('Content-Type: text/plain');
$encoded = SecretDecoderRing::encode('Hello, World!');
echo $encoded, PHP_EOL;
$decoded = SecretDecoderRing::decode($encoded);
echo $decoded, PHP_EOL;
?>
Thanks to everyone who participated in this challenge.

Edit: This post was recovered from search engine cache.
Last edited by McInfo on Tue Jun 15, 2010 11:39 am, edited 1 time in total.
watson516
Forum Contributor
Posts: 198
Joined: Mon Mar 20, 2006 9:19 pm
Location: Hamilton, Ontario

Re: [Challenge] Secret Decoder Ring

Post by watson516 »

Here is my version:

Code: Select all

class Decrypt {
    
    private $decryptMe;
    private $origPat = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&\'()*+,-./0123456789:;<=>?@';
    private $firstPat;
    private $secondPat;
    public $final;
    
    public function Decrypt($decrypt) {
        $this->decryptMe = $decrypt;
        $this->findPositions();
    }
    
    private function findPositions() {
        $first = substr($this->decryptMe,0,1);
        $second = substr($this->decryptMe,1,1);
        $this->firstPat = strstr($this->origPat,$first).strstr($this->origPat,$first,true);
        $this->secondPat = strstr($this->origPat,$second).strstr($this->origPat,$second,true);
        $this->loopThrough();
    }
    
    private function loopThrough() {
        $this->final = '';
        $count = 2;
        while($count < strlen($this->decryptMe)) {
            if($count%2) {
                //Take from firstPat
                $letPos=substr($this->decryptMe,$count,1);
                $letPost = strpos($this->secondPat,$letPos);
                $this->final .= substr($this->firstPat,$letPost,1);
            }else{
                //Take from secondPat
                $letPos=substr($this->decryptMe,$count,1);
                $letPost = strpos($this->firstPat,$letPos);
                $this->final .= substr($this->secondPat,$letPost,1);
                
            }
            $count++;
        }
    }
    
}
 
$decrypt='+F(+S#W|Y1Q|Y%T*X<dtT1d$F2J;H.F~P!I;Y$J;H+I!r;.*d+W J.d0T;U.T2J;Y$F0d';
$decrypt.='5T1d$F2J;X+Q2J d0M!d,Z6_(J;\%Y$T1Y;X,T%Q%S#d%Y;K+W;J2J.^+S!d!Q/JGd5T';
$decrypt.='1d)Z/Y;I+\*Q+F d|d}F L!d|S d|Y0F~M;N0d%S;F;W!U(^;U+X0r;9$J.J;F.J;Y$W!';
$decrypt.='J;G|I#J/dCL+Q p;X%Q2J.p;F*I;G.T*_!m;Y+d}J;H(F%R!I;F0d0M%X;F I.J/XUd$';
$decrypt.='Y0UUsJX*^ J2r~T)sKu"tO{|vQI!z w}zQKTFQyRt"IMxQyOxIdoM|S\'X;K+W;U(F5N*LI';
 
$dec = new Decrypt($decrypt);
echo $dec->final;
 
?>
Pretty simple but works.

Works with that second encoded string too. I win.
SimonMayer
Forum Commoner
Posts: 32
Joined: Wed Sep 09, 2009 6:40 pm

Re: [Challenge] Secret Decoder Ring

Post by SimonMayer »

Here is my effort. I originally had unexpected results with the submission of the string through $_POST, so I had to manually copy the text and escape " and $ characters. This works with both example strings.

Code: Select all

<?
    $string = "T:]U)M-G/['G/O*T.f:?*[:N{\ e}X{I&K~e/N e}U~KHecT:U-J
X:Z*e+X*\ e/N{Z:_*[:N{\ e.U'\ J:Z#K:V0`5R e2O/N*[/e.V*O'O)M:O/e!U-e \
X4U)K:K'Y q:_*[:S0Y/e~U2T'U{J:G:H{J\"K:G)J:G/Z{I#e\$Z:O)e{e-K+R4e+U.ZHenN X
e{X e/N-K e|G~M Y:m\"U'JFe.O'\ XFe{T~e|X*T5KCe/U:H e}R{O(K~e{Z:Z#O.e{J~X Y.
:N/Z+ It.T4J
\HI*SIuKLJyQGL{~KPJMHP{!~{{O|JL~wN{OyNs::#G)Q.e!U-e+R{_\$T\"s";
    $start_char_a = ord($string[0]);
    $start_char_b = ord($string[1]);
    for ($i = 2; $i < strlen($string); $i++)
    {
        echo "&#".ord($string[$i]).";";
    }
    echo "<br/><br/><br/>";
    
    
    $array_a = array();
    
    for($i = $start_char_a; $i <= 126; $i++)
    {
        array_push($array_a, $i);
    }
    for($i = 32; $i < $start_char_a; $i++)
    {
        array_push($array_a, $i);
    }
    
    $array_b = array();
    for($i = $start_char_b; $i <= 126; $i++)
    {
        array_push($array_b, $i);
    }
    for($i = 32; $i < $start_char_b; $i++)
    {
        array_push($array_b, $i);
    }
    
    for ($i = 2; $i < strlen($string); $i++)
    {
        if($i % 2)
        {
            $filtered_b = (array_keys($array_b, ord($string[$i])));
            echo "&#".$array_a[$filtered_b[0]].";";
        }
        else
        {
            $filtered_a = (array_keys($array_a, ord($string[$i])));
            echo "&#".$array_b[$filtered_a[0]].";";
        }
    }
?>
Image
TheOnly92
Forum Newbie
Posts: 19
Joined: Thu Jan 15, 2009 6:05 am

Re: [Challenge] Secret Decoder Ring

Post by TheOnly92 »

Hmm, might be late here, just posting a shorter and simpler solution without using array_shifts

Code: Select all

<?php
$text = <<<TEXT
+F(+S#W|Y1Q|Y%T*X<dtT1d$F2J;H.F~P!I;Y$J;H+I!r;.*d+W J.d0T;U.T2J;Y$F0d5T1d$F2J;X+Q2J d0M!d,Z6_(J;\%Y$T1Y;X,T%Q%S#d%Y;K+W;J2J.^+S!d!Q/JGd5T1d)Z/Y;I+\*Q+F d|d}F L!d|S d|Y0F~M;N0d%S;F;W!U(^;U+X0r;9$J.J;F.J;Y$W!J;G|I#J/dCL+Q p;X%Q2J.p;F*I;G.T*_!m;Y+d}J;H(F%R!I;F0d0M%X;F I.J/XUd$Y0UUsJX*^ J2r~T)sKu"tO{|vQI!z w}zQKTFQyRt"IMxQyOxIdoM|S'X;K+W;U(F5N*LI
TEXT;
$decoder_hint = substr($text,0,2);
// Construct the ASCII code table
$table = '';
for ($i=32;$i<=126;$i++) {
    $table .= chr($i);
}
// First table
$first = stristr($table,$decoder_hint[0]);
$pos = strpos($table,$decoder_hint[0]);
$first .= substr($table,0,$pos);
// Second table
$second = stristr($table,$decoder_hint[1]);
$pos = strpos($table,$decoder_hint[1]);
$second .= substr($table,0,$pos);
$decoded = '';
for ($i=2;$i<=strlen($text)-1;$i++) {
    $current = substr($text,$i,1);
    if ($i % 2 == 0) {
        // First table as reference, second table as answer
        $pos = strpos($first,$current);
        $decoded .= substr($second,$pos,1);
    } else {
        // Vice versa
        $pos = strpos($second,$current);
        $decoded .= substr($first,$pos,1);
    }
}
echo $decoded;
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: [Challenge] Secret Decoder Ring

Post by pickle »

Is the message in clear English? I'm close but there is some mispelling and extraneous characters - I'm wondering if they're supposed to be there or if my implementation is flawed.

Edit: Never mind - didn't realize the challenge had ended. Duh.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
krishnik
Forum Newbie
Posts: 9
Joined: Tue Dec 08, 2009 5:57 am

Re: [Challenge] Secret Decoder Ring

Post by krishnik »

Here is my code

Code: Select all

 
<?php
    error_reporting(E_ALL^E_NOTICE);
    $charset1=array (",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~"," ","!","\"","#","$","%","&","'","(",")","*");
    $charset2=array ("G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~"," ","!","\"","#","$","%","&","'","(",")","*","+",",","-","."," /","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E");
 
 
        
    $encrypted_val='+F(+S#W|Y1Q|Y%T*X<dtT1d$F2J;H.F~P!I;Y$J;H+I!r;.*d+W J.d0T;U.T2J;Y$F0d5T1d$F2J;X+Q2J d0M!d,Z6_(J;\%Y$T1Y;X,T%Q%S#d%Y;K+W;J2J.^+S!d!Q/JGd5T1d)Z/Y;I+\*Q+F d|d}F L!d|S d|Y0F~M;N0d%S;F;W!U(^;U+X0r;9$J.J;F.J;Y$W!J;G|I#J/dCL+Q p;X%Q2J.p;F*I;G.T*_!m;Y+d}J;H(F%R!I;F0d0M%X;F I.J/XUd$Y0UUsJX*^ J2r~T)sKu"tO{|vQI!z w}zQKTFQyRt"IMxQyOxIdoM|S\'X;K+W;U(F5N*LI';
    $len=strlen($encrypted_val);
    for($k=0;$k<=$len;$k++){
        $char=mb_substr($encrypted_val,$k,1);
        if($k!=0 && $k!=1){
            if($k%2==0){
                for($i=0;$i<=sizeof($charset1);$i++){
                    if($charset1[$i]==$char){
                        echo $charset2[$i];
                    }
                }
                $char;
            }else{
               for($i=0;$i<=sizeof($charset2);$i++){
                    if($charset2[$i]==$char){
                        echo $charset1[$i];
                    }
                }
            }
        }
    }
    ?>
 
Nikhil Krishnan
Post Reply