解决Hydra-Shield - PHP

时间:2015-10-17 14:42:26

标签: php arrays algorithm sorting

下面是这个算法问题的php脚本:

  

神盾局是一个秘密组织,负责任务   保护世界免受任何灾难。他们的主要克星是   组织名为HYDRA。不幸的是,HYDRA的一些成员了   渗透到神盾局阵营。神盾局需要找出所有这些   渗透者,以确保它没有受到损害。

     

执行董事兼首席神盾局成员尼克·弗瑞发现神盾局的每个人都可以向每个人发送一个SOS信号   他熟悉的其他神盾局成员。 HYDRA成员可能会伪造   SOS向其他人发送消息以使他人感到困惑,但他们永远无法收到   来自SHIELD成员的SOS消息。每个神盾局成员都会收到   SOS消息是另一个神盾局成员,他们反过来会有   从另一个神盾局成员那里收到,直到NickFury。屏蔽   有一个复杂的机制来捕获谁发送了一个SOS信号   谁。鉴于此信息,尼克需要有人写一个程序   可以查看这些数据并找出所有HYDRA成员。

Sample Input

Nick Fury : Tony Stark, Maria Hill, Norman Osborn
Hulk : Tony Stark, HawkEye, Rogers
Rogers : Thor, 
Tony Stark: Pepper Potts, Nick Fury
Agent 13 : Agent-X, Nick Fury, Hitler
Thor: HawkEye, BlackWidow
BlackWidow:Hawkeye
Maria Hill : Hulk, Rogers, Nick Fury
Agent-X : Agent 13, Rogers
Norman Osborn: Tony Stark, Thor

Sample Output

Agent 13, Agent-X, Hitler

的script.php

   <?php
    //this is the input
    $input="Nick Fury : Tony Stark, Maria Hill, Norman Osborn
    Hulk : Tony Stark, HawkEye, Rogers
    Rogers : Thor
    Tony Stark: Pepper Potts, Nick Fury
    Agent 13 : Agent-X, Nick Fury, Hitler
    Thor: HawkEye, BlackWidow
    BlackWidow:HawkEye
    Maria Hill : Hulk, Rogers, Nick Fury
    Agent-X : Agent 13, Rogers
    Norman Osborn: Tony Stark, Thor";

        /*this is an array for storing shield member names as 
           key-value pairs like Nick Fury=>Tony Stark, Maria Hill, Norman Osborn*/
            $shield=array();


            $keys=array();      //array for storing shield member names as keys
            $values=array();    //array for storing shield member names as value


            $shield_members=array();    //array which stores each valid shield member's name using below process
            //$hydra=array();


            $rows = explode("\n", $input);  //creating array of given input row wise



            $i=0;
            //considering each row at once
            while ($i<count($rows)) {
                # code...
                $temp=explode(":", $rows[$i]);  //exploding row
                $key=trim($temp[0]);            //getting key
                $value=trim($temp[1]);          //getting value

                $keys[]=$key;       //storing each key in keys[]

                $values[]=$value;   //storing each value in values[]
                $shield[$key]=$value;   //storing these key-value pair as array in shield[]
                $i++;
            }

            //loop to find all persons who are receiving messages from anyone
            $i=0;
            $recieiver_hydra=array();   //arrray to store all persons receiving messages
            while($i<count($values)){
                $temp = explode(",", $values[$i]); //exploding RHS values row wise
                $j=0;
                while ($j<count($temp)) {
                    # code...
                    if(!in_array($temp[$j], $recieiver_hydra))  //trying insert only unique values in recieiver_hydra[]
                        $recieiver_hydra[]=$temp[$j];           //========BUT NOT GETTING=======
                    $j++;

                }

                $i++;
            }


        $shield_members[]= "Nick Fury"; //starting from Nick Fury

        $temp = explode(",",$shield["Nick Fury"]);  //getting value from shield[] array for given key

        $i=0;
        while($i<count($temp)){
            $shield_members[]= $temp[$i];   //adding shield members which are valid not the hydra people
            $i++;
        }

        /* searching process for each valid shield member starting from nick fury upto last one found
            and storing them in the sheil_members[] array  */
        for($i=1; $i<30; $i++){         //=============HERE DON'T GETTING WHAT SHOULD BE THE CONDITION TO STOP EXECUTING
            if (array_key_exists(trim($shield_members[$i]),$shield))
                $temp = explode(",",$shield[trim($shield_members[$i])]);
            else continue;
             $j=0;
             while ($j<count($temp)) {
                # code...

                $shield_members[] = trim($temp[$j]);
                $j++;
             }


        }


        $i=0;
        //printing all valid members added to shield_members[] including duplicate values
        while ( $i<count($shield_members)) {
            # code...
            echo $shield_members[$i]."<br>";
            $i++;
        }

        asort($shield_members); //sorting them

        $res1 = array_diff($keys, $shield_members);     //finding difference and getting HYDRA members from LHS
        $res2= array_diff($recieiver_hydra, $shield_members);   //finding difference and getting HYDRA members from RHS ======BUT NOT GETTING





    /*
    <form action=<?php echo $_SERVER["PHP_SELF"]?> method="POST">
    **<i> Enter input in the textarea... </i>
    <textarea name="input" rows="10" cols="90"></textarea><br>
    <input type="submit" name="submit" value="Find HYDRA Members">

    </form>
    */
    ?>

根据我的编码和期望,$res1必须让所有来自LHS输入的HYDRA成员,而$res2必须拥有来自RHS输入的所有HYDRA成员。 但是在打印它们时,我得到了错误的结果。

$res1 = Array ( [4] => Agent 13 [8] => Agent-X )   //THIS IS CORRECT
$res2 = Array ( [3] => HawkEye [4] => Rogers [7] => Nick Fury 
                [8] => Agent-X [9] => Hitler [11] => BlackWidow 
                [13] => Agent 13 [14] => Thor )  //WRONG RESULTS

请帮我知道我做错了什么? (我不是算法方面的专家。我使用原始编码思想和知识制作了完整的代码。)

1 个答案:

答案 0 :(得分:2)

这听起来像是一些编程课程的练习。通常我会说,你应该自己解决这个问题(我认为这将是你的问题投票的原因),但这是一个有趣的问题,所以这是我的解决方案。

如果我需要实现一个新算法,我总是试图将问题分解为子问题。 这样做,

  • 更容易找到一个好的解决方案
  • 结果您获得了更易读的代码

所以第一个问题是将输入转换为数组结构以使用:

function transformInput($input) {
  foreach (explode("\n", $input) as $row) {
    list($receiver, $senders) = explode(':', $row);
    $memberTree[trim($receiver)] = array_map('trim', explode(',', $senders));    
  }
  return $memberTree;
}

第二个问题是找到所有真正的SHIELD成员:

function extractShieldMembers($memberTree, $startMember, $shieldMembers = array()) {
  $shieldMembers[] = $startMember;  
  if (array_key_exists($startMember, $memberTree)) {
    foreach ($memberTree[$startMember] as $member) {
      if (!in_array($member, $shieldMembers)) {
        $shieldMembers = array_merge(
          $shieldMembers, 
          extractShieldMembers($memberTree, $member, $shieldMembers)
        );
      }
    }
  }
  return $shieldMembers;
}

使用库中的这两个函数,很容易获得所有SHIELD成员的列表:

$memberTree = transformInput($input);
$shieldMembers = array_unique(extractShieldMembers($memberTree, 'Nick Fury'));

现在,在了解了谁真正属于神盾局之后,您可以找到所有拥有此功能的HYDRA成员:

function getHydraMembers($memberTree, $shieldMembers){
  $allMembers = array();
  foreach ($memberTree as $key => $value) {
    $allMembers[] = $key;
    $allMembers = array_merge($allMembers, $value);
  }
  return array_unique(array_diff($allMembers, $shieldMembers));
}

$hydraMembers = getHydraMembers($memberTree, $shieldMembers);

这是解决此问题的最佳方法吗? 我不这么认为,因为这只是一种快速的方法。 但正如您所看到的,如果您尝试将代码拆分为小型逻辑函数,则可以获得更易读的代码,以便更好地进行调试。 您也不需要尽可能多的临时变量和计数器。