草庐IT

张昌蒲 严教 卡牌计算器

coderChengL 2023-03-28 原文

1.描述

  玩过三国杀的朋友应该都知道有个将叫张昌蒲,他会随机给出N张卡牌,卡牌的点数在1-13之间,可能重复。现在要求把卡牌分为两堆,两边卡牌的点数之和必须相等,要求两堆的卡牌数之和尽量多。

  针对这个逻辑,我自己写了一些JAVA的实现,经过测试可行,下面给出代码,有兴趣的朋友可以看看,有改进的地方欢迎指出!

2.代码如下

计算分配方式的代码:

  1 public class CalculateCard {
  2 
  3     public static void main(String[] args) {
  4         Scanner scanner = new Scanner(System.in);
  5         System.out.println("请输入严教牌,按点数,以空格割开,如(13 11 10):");
  6         String input = scanner.nextLine();
  7         System.out.println(input);
  8         String[] inputCards = input.split(" ");
  9         List<Integer> list = new ArrayList<>();
 10         try {
 11             Arrays.stream(inputCards).forEach(card -> list.add(Integer.parseInt(card)));
 12         }catch (NumberFormatException e) {
 13             System.out.println("请输入数字,牌的点数在1-13");
 14         }
 15         AtomicBoolean isCorrect = new AtomicBoolean(true);
 16         list.forEach(item -> isCorrect.set(item <= 13 && item >= 1));
 17         if(!isCorrect.get()){
 18             System.out.println("----请输入数字,牌的点数在1-13");
 19         }
 20         calculateAll(list);
 21     }
 22 
 23     /**
 24      * 计算所有可能的分配方式,并找到使用卡牌最多的组合方式
 25      * @param list 所有输入的数字
 26      */
 27     private static void calculateAll(List<Integer> list){
 28         //存放所有的可行分配方式
 29         List<Pair<Integer,Pair<String,String>>> okResult = new ArrayList<>();
 30         //存放使用牌数最多的分配方式
 31         List<Pair<Integer,Pair<String,String>>> okResultLast = new ArrayList<>();
 32         //存放所有数字的组合
 33         List<Pair<Integer,Pair<Integer,String>>> result = new ArrayList<>();
 34         //用于存放已经找到的分配方式,排除重复分配
 35         List<String> listAdd = new ArrayList<>();
 36         //获取所有的数字组合方式
 37         getAllComb(list,result);
 38         int countNum = 0;
 39         //遍历所有组合方式
 40         for (int i = 0; i < result.size(); i++) {
 41             /*
 42              * 思路
 43              * 1.取出其中一种组合,拿到这个组合的点数和sum
 44              * 2.将当前组合中的所有数字放在一个List--currentList中
 45              * 3.从原来得包含所有点数的卡牌集合中筛选出去掉currentList所有数字的其他数字,放在listLeft中
 46              * 5.获得listLeft中所有数字的全部组合方式,放在result1中
 47              * 6.遍历result1,比对总和与sum是否相等,相等则为一种成功的组合方式。
 48              * 7.找到成功组合中使用卡牌最多的组合方式
 49              */
 50             Pair<Integer,Pair<Integer,String>> pair = result.get(i);
 51             int sum = pair.getValue().getKey();
 52             int numCount = pair.getKey();
 53             String com = pair.getValue().getValue();
 54             String[] numStr = com.split(",");
 55             List<Integer> listLeft = new ArrayList<>();
 56             List<Integer> currentList = new ArrayList<>();
 57             for (int j = 0; j < numStr.length; j++) {
 58                 currentList.add(Integer.parseInt(numStr[j]));
 59             }
 60             for (int j = 0; j < list.size(); j++) {
 61                 if(!currentList.contains(list.get(j))) listLeft.add(list.get(j));
 62             }
 63             List<Pair<Integer,Pair<Integer,String>>> result1 = new ArrayList<>();
 64             getAllComb(listLeft,result1);
 65             for (int j = 0; j < result1.size(); j++) {
 66                 Pair<Integer,Pair<Integer,String>> pair1 = result1.get(j);
 67                 int leftSum = pair1.getValue().getKey();
 68                 int leftCount = pair1.getKey();
 69                 String com1 = pair1.getValue().getValue();
 70                 countNum = countNum == 0 ? numCount + leftCount : countNum;
 71                 if(leftSum == sum && countNum <= numCount + leftCount){
 72                     //计数,如果组合中的数字个数更大,则移除结果集,重新添加,只保存最多的
 73                     if(countNum != 0 && countNum < numCount+leftCount){
 74                         countNum = numCount + leftCount;
 75                         okResultLast.clear();
 76                     }
 77                     //去除牌堆左右互换的匹配组合
 78                     if(listAdd.contains(com1) || listAdd.contains(com)) continue;
 79                     listAdd.add(com1);
 80                     okResult.add(new Pair<>(numCount+leftCount,new Pair<>(com,com1)));
 81                     okResultLast.add(new Pair<>(numCount+leftCount,new Pair<>(com,com1)));
 82                 }
 83             }
 84         }
 85 //        System.out.println("所有组合:");
 86 //        for (int i = 0; i < okResult.size(); i++) {
 87 //            Pair<Integer,Pair<String,String>> resultPair = okResult.get(i);
 88 //            System.out.println("组合的总牌数:"+resultPair.getKey() +
 89 //                    "  ===>组合1为:  " + resultPair.getValue().getKey() +
 90 //                    "  ===>组合2为:  " + resultPair.getValue().getValue());
 91 //        }
 92         System.out.println("=================================================");
 93         System.out.println("使用卡牌最多的组合方式:");
 94         System.out.println("=================================================");
 95         for (int i = 0; i < okResultLast.size(); i++) {
 96             Pair<Integer,Pair<String,String>> resultPair = okResultLast.get(i);
 97             System.out.println("当前分配式方"+(i+1)+"总牌数:"+resultPair.getKey() +
 98                                "\n====>堆一卡牌点数分别为:  " + resultPair.getValue().getKey() +
 99                                "\n====>堆二卡牌点数分别为:  " + resultPair.getValue().getValue());
100         }
101         System.out.println("=================================================");
102     }
103 
104     /**
105      * 获得所有可能的组合
106      * 如数字列表为:【1,2,3】
107      * 那么得到的所有组合为【1】,【2】,【3】,【1,2】,【1,3】,【2,3】,【1,2,3】
108      * @param list 所有数字
109      * @param result 返回的组合集合
110      */
111     private static void getAllComb(List<Integer> list,List<Pair<Integer,Pair<Integer,String>>> result){
112         List<String> com = new ArrayList<>();
113         for (int i = 1; i != list.size() + 1; i++) {
114             ComputCombinations.getCombination(result,list,0,i,com);
115         }
116 //        result.stream().forEach(item -> System.out.println("数字数:"+ item.getKey()+
117 //                "=====>总值:"+ item.getValue().getKey()+ " 内容:" + item.getValue().getValue()));
118     }
119 }

计算数字组合的算法:

 1 public static void getCombination(List<Pair<Integer,Pair<Integer,String>>> result,
 2                                                     List<Integer> list, int start, int len , List<String> com){
 3         if(len == 0){
 4             String s = "";
 5             for (int i = 0; i != com.size() ; i++) {
 6                 s = s.concat(com.get(i));
 7             }
 8             String comStr = s.substring(0,s.length() - 1);
 9             String[] all = comStr.split(",");
10             AtomicInteger sum = new AtomicInteger();
11             Arrays.stream(all).forEach(item -> sum.addAndGet(Integer.parseInt(item)));
12             result.add(new Pair<>(com.size(),new Pair<>(sum.get(),comStr)));
13             return;
14         }
15         if(start == list.size()){
16             return;
17         }
18         com.add(list.get(start)+",");
19         getCombination(result,list, start+1,len - 1,com);
20         com.remove(com.size()-1);
21         getCombination(result,list,start+1,len,com);
22     }

 

测试结果:

 

 

有可以改进的地方,欢迎指出...

有关张昌蒲 严教 卡牌计算器的更多相关文章

  1. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  2. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  3. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  4. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

    给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

  5. arrays - 计算数组中的匹配元素 - 2

    给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at

  6. ruby-on-rails - 如何计算 Ruby/Rails 中 JSON 对象的数量 - 2

    Ruby中如何“一般地”计算以下格式(有根、无根)的JSON对象的数量?一般来说,我的意思是元素可能不同(例如“标题”被称为其他东西)。没有根:{[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]}根包裹:{"posts":[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]} 最佳答案 首先,withoutroot代码不是有效的json格式。它将没有包

  7. ruby - 如何计算自 Ruby 中给定日期以来的周数? - 2

    目标我正在尝试计算自给定日期以来周的距离,而无需跳过任何步骤。我更喜欢用普通的Ruby来做,但ActiveSupport无疑是一个可以接受的选择。我的代码我写了以下内容,这似乎可行,但对我来说似乎还有很长的路要走。require'date'DAYS_IN_WEEK=7.0defweeks_sincedate_stringdate=Date.parsedate_stringdays=Date.today-dateweeks=days/DAYS_IN_WEEKweeks.round2endweeks_since'2015-06-15'#=>32.57ActiveSupport的#weeks

  8. 最新版人脸识别小程序 图片识别 生成二维码签到 地图上选点进行位置签到 计算签到距离 课程会议活动打卡日常考勤 上课签到打卡考勤口令签到 - 2

    技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进

  9. ruby - 如何计算两个字符串共有的字符数? - 2

    如何计算两个字符串之间的字符交集?例如(假设我们有一个名为String.intersection的方法):"abc".intersection("ab")=2"hello".intersection("hallo")=4好的,男孩女孩们,感谢你们的大量反馈。更多示例:"aaa".intersection("a")=1"foo".intersection("bar")=0"abc".intersection("bc")=2"abc".intersection("ac")=2"abba".intersection("aa")=2一些补充说明:维基百科定义intersection如下:Int

  10. python - 如何计算文件中唯一字符的数量? - 2

    给定一个包含各种语言字符的UTF-8文件,我如何计算它包含的唯一字符的数量,同时排除选定数量的符号(例如:“!”、“@”、"#",".")从这个算起? 最佳答案 这是一个bash解决方案。:)bash$perl-CSD-ne'BEGIN{$s{$_}++forsplit//,q(!@#.)}$s{$_}++||$c++forsplit//;END{print"$c\n"}'*.utf8 关于python-如何计算文件中唯一字符的数量?,我们在StackOverflow上找到一个类似的问题

随机推荐