草庐IT

java - 如何找到公式的所有可能解,例如 100*7-8*3+7? (10 只猫中有 8 只做倒计时求解器)

coder 2024-03-08 原文

为了好玩,我决定编写一个简单的程序来解决 10 只猫中有 8 只猫倒计时的问题 number puzzle ,链接是倒计时形式,但规则相同。所以我的程序简单地遍历了 AxBxCxDxExF 的所有可能组合,其中字母是数字,“x”是 +、-、/和 *。这是它的代码:

private void combineRecursive( int step, int[] numbers, int[] operations, int combination[]){
    if( step%2==0){//even steps are numbers
        for( int i=0; i<numbers.length; i++){
            combination[ step] = numbers[ i];
            if(step==10){//last step, all 6 numbers and 5 operations are placed
                int index = Solution.isSolutionCorrect( combination, targetSolution);
                if( index>=0){
                    solutionQueue.addLast( new Solution( combination, index));
                }
                return;
            }
            combineRecursive( step+1, removeIndex( i, numbers), operations, combination);
        }
    }else{//odd steps are operations
        for( int i=0; i<operations.length; i++){
            combination[ step] = operations[ i];
            combineRecursive( step+1, numbers, operations, combination);
        }
    }
}

这是我用来测试组合是否符合我的要求的方法。

public static int isSolutionCorrect( int[] combination, int targetSolution){
    double result = combination[0];
    //just a test
    if( Arrays.equals( combination, new int[]{100,'*',7,'-',8,'*',3,'+',7,'+',50})){
        System.out.println( "found");
    }
    for( int i=1; i<combination.length; i++){
        if(i%2!=0){
            switch( (char)combination[i]){
                case '+': result+= combination[++i];break;
                case '-': result-= combination[++i];break;
                case '*': result*= combination[++i];break;
                case '/': result/= combination[++i];break;
            }
        }
        if( targetSolution==result){
            return i;
        }
    }       
    return targetSolution==result?0:-1;
}

所以在上一集中我发现我的代码有问题。这是其中一个难题的解决方案。

(10*7)-(8*(3+7))

我注意到我确实找到了这个组合“10*7-8*3+7”(两次),但是因为我通过从左到右的操作来检查解决方案,所以我实际上并没有找到所有答案。我只检查这样的解决方案 ((((10*7)-8)*3)+7)。所以即使我找到了组合,我也没有正确的顺序。

所以现在的问题是我如何测试所有可能的数学顺序,例如 (10*7)-(8*(3+7))、(10*7)-((8*3)+7) 或10*(7-8)*(3+7)?我虽然可以使用带有操作的平衡树作为平衡节点。但我仍然不知道如何在不绕过公式的情况下完成所有可能的组合。

(10*7)-(8*(3+7))
          -
     /        \
    *         *
  /   \      /  \
700   7     8    +
                / \
              7    3

(10*7)-((8*3)+7)
          -
     /        \
    *         +
  /   \      /  \
700   7     *    7
           / \
          8  3

10*(7-8)*(3+7)

                 *
           /           \
          *
     /        \         10
    -          +
  /   \      /  \
7     8     3    7

我如何在代码中执行此操作?不是在寻找已解决的代码更多的是我应该如何改变视角来修复它。我不知道为什么我对此感到难过。

关于我:计算机科学四年级,不是编程新手或新手(我至少喜欢相信 ;))

最佳答案

使用表示表达式的专用类而不是数组更容易解决这个问题。然后你可以简单地枚举所有可能的树。混合 another answer that I wrote for a similar task , 和一个 answer that shows how to generate all binary trees给了这个:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class NumberPuzzleWithCats
{
    public static void main(String[] args)
    {
        List<Integer> numbers = Arrays.asList(10,7,8,3,7);
        solve(numbers);
    }

    private static void solve(List<Integer> numbers)
    {
        List<Node> nodes = new ArrayList<Node>();
        for (int i=0; i<numbers.size(); i++)
        {
            Integer number = numbers.get(i);
            nodes.add(new Node(number));
        }
        System.out.println(nodes);
        List<Node> all = create(nodes);
        System.out.println("Found "+all.size()+" combinations");


        for (Node node : all)
        {
            String s = node.toString();
            System.out.print(s);
            if (s.equals("((10*7)-(8*(3+7)))"))
            {
                System.out.println(" <--- There is is :)");
            }
            else
            {
                System.out.println();
            }
        }
    }

    private static List<Node> create(Node n0, Node n1)
    {
        List<Node> nodes = new ArrayList<Node>();
        nodes.add(new Node(n0, '+', n1));
        nodes.add(new Node(n0, '*', n1));
        nodes.add(new Node(n0, '-', n1));
        nodes.add(new Node(n0, '/', n1));
        nodes.add(new Node(n1, '+', n0));
        nodes.add(new Node(n1, '*', n0));
        nodes.add(new Node(n1, '-', n0));
        nodes.add(new Node(n1, '/', n0));
        return nodes;
    }

    private static List<Node> create(List<Node> nodes)
    {
        if (nodes.size() == 1)
        {
            return nodes;
        }
        if (nodes.size() == 2)
        {
            Node n0 = nodes.get(0);
            Node n1 = nodes.get(1);
            return create(n0, n1);
        }
        List<Node> nextNodes = new ArrayList<Node>();
        for (int i=1; i<nodes.size()-1; i++)
        {
            List<Node> s0 = create(nodes.subList(0, i));
            List<Node> s1 = create(nodes.subList(i, nodes.size()));
            for (Node n0 : s0)
            {
                for (Node n1 : s1)
                {
                    nextNodes.addAll(create(n0, n1));
                }
            }
        }
        return nextNodes;
    }

    static class Node
    {
        int value;
        Node left;
        Character op;
        Node right;

        Node(Node left, Character op, Node right)
        {
            this.left = left;
            this.op = op;
            this.right = right;
        }
        Node(Integer value)
        {
            this.value = value;
        }

        @Override
        public String toString()
        {
            if (op == null)
            {
                return String.valueOf(value);
            }
            return "("+left.toString()+op+right.toString()+")";
        }
    }
}

它将打印所有创建的组合,包括您一直在寻找的组合:

[10, 7, 8, 3, 7]
Found 16384 combinations
(10+(7+(8+(3+7))))
(10*(7+(8+(3+7))))
...
((10*7)+(8*(3+7)))
((10*7)*(8*(3+7)))
((10*7)-(8*(3+7))) <--- There is is :)
((10*7)/(8*(3+7)))
((8*(3+7))+(10*7))
...
((7/3)-((8/7)/10))
((7/3)/((8/7)/10))

当然,通过比较 String 表示来检查是否找到正确的解决方案是......“非常实用”,这样说,但我认为生成的实际方法是这里重要的是什么。

(我希望这真的是您一直在寻找的 - 我无法查看您链接到的网站...)

关于java - 如何找到公式的所有可能解,例如 100*7-8*3+7? (10 只猫中有 8 只做倒计时求解器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31597886/

有关java - 如何找到公式的所有可能解,例如 100*7-8*3+7? (10 只猫中有 8 只做倒计时求解器)的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  7. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  8. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  9. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  10. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

随机推荐