4

There is quite a popular program (I forget the name) which generates triangles, where on each side there is a question or answer, and each triangle fits together such that the answer on one triangle matches the question on another, and when put together correctly it creates a larger shape (usually a regular hexagon).

I am trying to write a script, where $t is a 2D array containing the cards:

$t = array();

// $t['1'] represents the 'center' triangle in this basic example
$t['1'] = array(
    '1', // One side of T1, which is an answer
    '3-1', // Another side, this is a question
    '2+1' // Final side, another question
);

// These cards go around the outside of the center card
$t['2'] = array(
    '2-1' // This is a question on one side of T2, the other sides are blank
);
$t['3'] = array(
    '2' // This is an answer on one side of T3, the other sides are blank
);
$t['4'] = array(
    '3' // This is an answer on one side of T4, the other sides are blank
);

What now need it to do, is say, for example, "T1-S1 matches with T2, T1-S2 matches with T3, T1-S3 matches with T4". I have tried, and what I have so far is below:

foreach ($t as $array) {
    foreach ($array as $row) {
        $i = 0;
        while ($i <= 4) {
            if(in_array($row, $t[$i])){
                echo $row . ' matches with triangle ' . $i . '<br />';
            }
            $i++;
        }
    }
}

Note: The code above is for a simplified version where all the questions were 'solved', and it was just matching the two sides.

After running my code, I get this output:

1 matches with triangle 1
1 matches with triangle 2
2 matches with triangle 1
2 matches with triangle 3
3 matches with triangle 1
3 matches with triangle 4
1 matches with triangle 1
1 matches with triangle 2
2 matches with triangle 1
2 matches with triangle 3
3 matches with triangle 1
3 matches with triangle 4

The problem is, that $row only tells me the side of a triangle, not the actual triangle. So my question is this:

How do I make my script work, such that it outputs "Ta-Sb matches with Tc-Sd" where a is the triangle, b is the side, and c is the triangle it matches with, and d is the side it matches with, assuming that in each array the values for the sides are in order?

I hope that the question is clear, however feel free to ask any questions.

Also, ideally once it has matched Ta-Sb with Tc-Sd, it should not match Tc-Sd with Ta-Sb. Is that possible too?

Benedict Lewis
  • 2,733
  • 7
  • 37
  • 78

2 Answers2

1

I find it easier to approach these types of problems with objects rather than arrays. Too complicated to remember what each array level means and how they line up. So I might do something like this:

<?
// I say Polygon instead of triangle because ideally the logic should scale for squares, octagons, anything! But start with triangles of course.
class Polygon{ 
  var $Sides = array(); // Side objects - there should be 3 of them for a triangle
  var $matches = array(); // holds the ids of the matching polygonn - keys line up with $Sides

  function __construct(){
    $Sides[0] = new Side();
    $Sides[1] = new Side();
    $Sides[2] = new Side();
  }

}

class Side{
  var $Question; // Question object
  var $state; // 'q' or 'a' - does this side show the question or answer?

  function __construct(){
    $Question = new Question();
  }

}

class Question{
  var $id; // database id of the question
  var $question;
  var $answer;
}
?>

To populate:

<?php

$Triangle[0]=new Polygon();
$Triangle[0]->Side[0]->Question->id=1;
$Triangle[0]->Side[0]->Question->question='Yo momma serves more requests than what?';
$Triangle[0]->Side[0]->Question->answer='HTTP';
$Triangle[0]->Side[0]->state='q'; // This side shows the question
$Triangle[0]->matches[0]= 4; // Side 0 of this triangle matches a side of triangle 4

// write a loop that does this for all triangles using whatever your logic is for matching them up

?>

Now you can easily know which triangle, side, question, or match you're dealing with by saying for example:

$Polygon[2]->Sides[1]->state (means that side of that triangle should show an answer not a question )

$Polygon[0]->Sides[3]->Question->id (would hold a question's id)

$Polygon[1]->matches[2] (would hold the key of the triangle that matches side 2 of polygon 1)

It might feel like a leap if you're not used to objects, but this is a pretty easy way into it, you can just treat them like glorified arrays and forget about all the other stuff objects can do for now.

After you fill them with values - to get the matches you just loop through each Polygon and output whatever you need.

Hope this helps!

Syntax Error
  • 4,475
  • 2
  • 22
  • 33
  • With this though, It looks like you have to state what triangle it matches with (`$Triangle[0]->matches[0]= 4;`) – Benedict Lewis Sep 14 '13 at 05:03
  • I don't know that you would have to, but it seems like a convenient thing to keep track of. If you leave out matches you could probably just use the question id's to see if the sides matched up. This is just a way to organize what you're keeping track of so that it's easy to work with - how you use these objects is up to you. – Syntax Error Sep 14 '13 at 06:53
  • Oh, I understand. I thought you were suggesting this as a total solution, not just as something to help on the way. One of the things that it needs to be able to do is calculate a mathematical string (`1+2`). Is there a better way than looping through `try eval('$ans=STRING)`? – Benedict Lewis Sep 14 '13 at 09:00
  • You shouldn't use eval(). I found information on what you should do here: http://stackoverflow.com/questions/5057320/php-function-to-evaluate-string-like-2-1-as-arithmetic-2-1-1 – Syntax Error Sep 14 '13 at 16:31
0

Does this help?

foreach ($t as $ti => $array) {
    foreach ($array as $ri => $row) {
        $i = 0;
        while ($i <= 4) {
            if(in_array($row, $t[$i])){
                echo $row.' '.$ti.' '.$ri.' matches with triangle ' . $i . '<br />';
            }
            $i++;
        }
    }
}
Andy Gee
  • 3,149
  • 2
  • 29
  • 44