Page 2 of 2

Re: [Challenge] Conditioning

Posted: Wed Jan 27, 2010 2:25 pm
by McInfo
VladSun wrote:What's the importance of the N (in this case 50) period? Is it a must for your design or not?
There is no significance to the conditions I chose other than the number of conditions is greater than the number of allowed if statements. I chose the ranges I did because they seemed realistic and to make people think there might be some hidden relationship. Maybe there is, but not by design. The "pattern that I think is somewhat clever" is related to changing a variable based on a where it fits into a group of unequal conditions.

Edit: This post was recovered from search engine cache.

Re: [Challenge] Conditioning

Posted: Fri Jan 29, 2010 1:27 pm
by McInfo
This is my solution.

Code: Select all

<?php
$x = (int) $_GET['x'];
$y = (int) $_GET['y'];
 
function act (&$x, $new, $condition) {
    if ($condition)
        $x = $new;
    return $condition;
}
 
if ( ! act($x,        0, ($y <  1)            )
&&   ! act($x, $x +  $y, ( 0 < $y && $y <  50))
&&   ! act($x, $x +  50, (49 < $y && $y < 100))
&&   ! act($x, $x + 100, (99 < $y)            )
);
 
var_dump($x, $y);
It uses the fact that multiple conditions joined by and will be evaluated in order only until one of them is false.

This challenge was inspired by my solution to the "Colour rotation" challenge.

Edit: This post was recovered from search engine cache.

Re: [Challenge] Conditioning

Posted: Fri Jan 29, 2010 4:36 pm
by VladSun
:) Nice one. Bravo! :)

I found it's called "short-circuit evaluation". I remember, Turbo Pascal has a special compiler flag used to enable or disable short-circuit evaluation of the expressions in an if statement, though I think it's always enabled in modern languages.

It's also widely used in bash scripting:

Code: Select all

./configure && make && make install
Thats' how every command will be executed only and if only the previous one has return 0 error code ( exit(0) ).

Re: [Challenge] Conditioning

Posted: Fri Jan 29, 2010 6:13 pm
by McInfo
Thanks for finding that Wikipedia page. It's interesting to see how different languages handle multiple conditions.

Edit: This post was recovered from search engine cache.

Re: [Challenge] Conditioning

Posted: Fri Jan 29, 2010 7:04 pm
by AbraCadaver
I vote for the prize going to VladSun for either the binary logic or the lookup table. Both sweet!

Re: [Challenge] Conditioning

Posted: Sat Jan 30, 2010 4:15 am
by VladSun
Prize?!? What prize?!? There is a prize?!? Yahooooooooooo :rofl:

Gi'me, gi'me, gi'me :mrgreen:

PS: It's the min()/max() solution I like most - it was harder to build ;)

Re: [Challenge] Conditioning

Posted: Sat Jan 30, 2010 12:53 pm
by McInfo
I never promised prizes. How about praise to everyone who submitted a solution (especially VladSun for having the most variety)?

If anyone can come up with another solution to this challenge, I would still like to see it.

Edit: This post was recovered from search engine cache.

Re: [Challenge] Conditioning

Posted: Sat Mar 06, 2010 11:49 am
by josh
Maybe I'm stating the obvious but it took me a minute to figure out. When the array is populated whichever expression gets evaluated to true gets type cast from a boolean to an integer (one), which is then accessed in the return

Very intriguing stuff. It seems like it'd be way over my head to ever work on such constructs. I would never intentionally use this technique personally ;-) I'd rather see a couple ugly if statements tucked away with code collapse.

Only interest I'd have is if I had to maintain code that abused the technique lol

Re: [Challenge] Conditioning

Posted: Sun Mar 07, 2010 4:19 pm
by VladSun
Well a "pure" lookup table should be constructed like this:

Code: Select all

 
$a1 = $y < 1;
$a2 = $y < 50;
$a3 = $y < 100;
 
$lt[ $a1][ $a2][ $a3]  = 0;
$lt[!$a1][ $a2][ $a3]  = $y + $x;
$lt[!$a1][!$a2][ $a3]  = 50 + $x;
$lt[!$a1][!$a2][!$a3] = 100 + $x;
 
/*$lt = array
(
    $y < 1                  => 0,
    $y >= 1 && $y < 50      => $y + $x,
    $y >= 50 && $y < 100    => 50 + $x,
    $y >= 100               => 100 + $x,
);*/
But it's obvious that $a1, $a2, $a3 are extremely correlated:

Code: Select all

$a1 == true    => $a2 == false, $a3 == false
...
$a2 == false   => $a1 == false
$a3 == false   => $a1 == false, $a2 == false
...
etc.

So it can be written in a shorter form ;)


There are obvious disadvantages when using such "look up" tables - every "address" and it's corresponding "value" MUST be evaluated before the lookup action takes place.

Re: [Challenge] Conditioning

Posted: Sun Mar 07, 2010 4:23 pm
by Eran
I've begun to use this technique to replace tedious switch statements. I'm really liking it so far :)

Re: [Challenge] Conditioning

Posted: Sun Mar 07, 2010 4:26 pm
by VladSun
Nice to know somebody finds my stuff useful :) :)

Re: [Challenge] Conditioning

Posted: Sun Mar 07, 2010 6:35 pm
by josh
pytrin wrote:I've begun to use this technique to replace tedious switch statements. I'm really liking it so far :)
I think learning the stuff is fun & important because we'll all have to debug code like this.

But I'm just wondering what potential advantages you see in it that would make you actually rewrite a switch statement to this technique? Do you have a boss that reprimands you for using more than one curly brace for a conditional? Do you find the stuff "readable"? (FYI I do not). It is more "mental juggling" in my opinion

Re: [Challenge] Conditioning

Posted: Sun Mar 07, 2010 6:51 pm
by Eran
I find it much more readable, to be honest. When you have a set of predetermined values that depend on ranges of a variable, it is much easier to see all the values in an array format than in otherwise a much longer switch statement. For example, compare the following pieces of code which both return a screen-size range for laptops depending on a given value -
The original:

Code: Select all

switch ($screen) {
    case $screen < 12 : 
        $filters['screen'] = '8-12';
        break;
    case $screen >= 12 && $screen < 14 :
        $filters['screen'] = '12-14';
        break;
    case $screen >= 14 && $screen < 15 : 
        $filters['screen'] = '14-15';
        break;
    case $screen >= 15 && $screen < 16 : 
        $filters['screen'] = '15-16';
        break;
    case $screen >= 16 && $screen < 17 :
        $filters['screen'] = '16-17';
        break;
    case $screen >= 17 : 
        $filters['screen'] = '17-20';
        break;
}
 
Revised:

Code: Select all

$screenRange = array (
    $screen < 12                    => '8-12',
    $screen >= 12 && $screen < 14   => '12-14',
    $screen >= 14 && $screen < 15   => '14-15',
    $screen >= 15 && $screen < 16   => '15-16',
    $screen >= 16 && $screen < 17   => '16-17',
    $screen >= 17                   => '17-20'
);
$filters['screen'] = $screenRange[1];
It's not "mental juggling" once you're familiar with the concept. Then it's no different than any other language structure.

Re: [Challenge] Conditioning

Posted: Mon Mar 08, 2010 3:57 am
by VladSun
Another way to write this is:

Code: Select all

$screenRange = array 
(
    1               => '17-20'                                         
    $screen < 17    => '16-17'
    $screen < 16    => '15-16',
    $screen < 15    => '14-15',
    $screen < 14    => '12-14',
    $screen < 12    => '8-12',
);
$filters['screen'] = $screenRange[1];
it's the analog of:

Code: Select all

if ($screen < 12)
   return '8-12';
elseif ($screen < 14)
   return '12-14';
...
else
   return '17-20';

Re: [Challenge] Conditioning

Posted: Mon Mar 08, 2010 4:05 am
by josh
Yes that does look cleaner (if you are familiar with the concept). Thanks for clarifying.

Also I would advise if using in a real system, would advise a comment right before the return statement (something that at least provides a term someone can type into google to learn about this pattern). Or maybe not a comment but using the word "lookup" in the function name so people know what the heck it does ;-)
and instead of hard coding the integer "one", making a constant like self::ScreenSize, and self::DefaultSize then I think I would be hard pressed to come up with any more gripes