《程序员》2007第十期算法擂台之JAVA解法

题目:
[quote]
人和计算机做猜数游戏.人默想一个四位数,由计算机来猜.计算机将所猜的数据显示到屏幕上,并问两个问题:一,有几个数字猜对了;二,猜对的数字中有几个位置也对了.人通过键盘来回答这两个问题。计算机一次又一次地猜,直到猜对位置。
为了简化输入输出,计算机每次输出一个四位数,然后人输入两个用空格分开的数,分别表示有几个数字猜对,有几个数字位置也对。下面有某次猜数过程:人默认的数是3422,奇数行是计算机猜的数,偶数行是人输入的信息。在这个例子中,计算机第五次猜中了数,在人输入4 4后程序结束退出.
请你写一个这样的猜数游戏,看看你所想的数能在几次后被程序猜中。[color=red]如果在猜数过程中,计算机发现人故意欺骗,输入了不正确的信息,那么程序将输出0然后直接退出.[/color][/quote]
[color=blue]
例子:
6897
0 0
5555
0 0
4444
1 1
4333
2 0
3422
4 4[/color]

算法描叙:
每次从剩下的可能值中选择能使下一次筛选后可能值最少(平均意义下)的数去猜。

算法效果:
不甚理想,平均需要5.8步才能猜对。下面是统计数据:
Step[k] n x 表示使用k步猜对的数字有n个,x表示在总游戏数中占得比例:
Step[ 1] 1 0.0001
Step[ 2] 13 0.0013
Step[ 3] 110 0.0110
Step[ 4] 713 0.0713
Step[ 5] 2792 0.2792
Step[ 6] 4440 0.4440
Step[ 7] 1553 0.1553
Step[ 8] 277 0.0277
Step[ 9] 82 0.0082
Step[10] 19 0.0019
Total: 57824 steps 10000 games
Use time: 420266 ms

代码:
[code]

import java.util.*;

/**
  猜数字游戏
@author Eastsun
@version 2.0 2007/10/15
*/
public class NumberGuess{
public static void main(String[] args){
Scanner s =new Scanner(System.in);
AI solver =new AI();
try{
System.out.println(solver.firstGuess());
int b =s.nextInt();
int a =s.nextInt();
while(!(a==Item.SIZE&&b==Item.SIZE)){
System.out.println(solver.nextGuess(a,b));
b =s.nextInt();
a =s.nextInt();
}
}catch(IllegalArgumentException ex){
System.out.println("0");
}
}
}

class AI{
private static final Item[] ITEMS_BUFFER ={
new Item(56),
new Item(156),
new Item(256),
new Item(145),
new Item(135),
new Item(235),
new Item(123),
new Item(1322),
new Item(1124),
new Item(234),
new Item(2341),
new Item(1342),
new Item(1243),
null,
new Item(1234)
};
//可能的答案
private List<Item> candidates;

//最近一次的猜测
private Item lastGuess;

//已经猜过的次数
private int step;

/**
第一次猜测
*/
public Item firstGuess(){
step =1;
//初始化candidates为所有可能的答案
candidates =new LinkedList<Item>(Item.ALL_POSSIBLE_ITEMS);
//选择"1234"作为第一次的猜测.事实上任意一个四个数字各不相同的都可以,在统计意义下效果一样
lastGuess = new Item(1234); //
return lastGuess;
}

/**
根据上次的猜测结果得到下一次猜测
*/
public Item nextGuess(int a,int b){
step ++;
//根据上次结果对候选集进行过滤
filter(candidates,lastGuess,a,b);
//如果候选集为空,说明输入的数据有误
if(candidates.isEmpty()) throw new IllegalArgumentException();

if(step ==2){
lastGuess = ITEMS_BUFFER[b*(b+1)/2+a];
return lastGuess;
}
//从剩下的候选集中取出权重最小那个作为下一次的猜测
int min =Integer.MAX_VALUE;
for(Item guess : candidates){
int weight =weight(candidates, guess);
if(weight <min){
min =weight;
lastGuess =guess;
}
}
return lastGuess;
}

/**
将list中所有用guess猜答案不是(b,a)的过滤掉
*/
public static void filter(List<Item> list,Item guess,int a,int b){
for(Iterator<Item> itr =list.iterator();itr.hasNext();){
if(!Item.isMatch(itr.next(),guess,a,b)) itr.remove();
}
}


/**
用guess去猜结果集list时的权重,这个值越小越好
*/
public static int weight(List<Item> list,Item guess){
int[] count =new int[(Item.SIZE+1)*(Item.SIZE+2)/2];
for(Item word :list){
int a =Item.getA(word,guess);
int b =Item.getB(word,guess);
int index =(b+1)*b/2 +a; //hash for (b,a)
count[index] ++;
}
int value =0;
for(int c : count)
value += c*c;
return value;
}
}

class Item {
/**
数字位数
*/
public static final int SIZE =4;

//一个包含了所有可能解的不可修改的list
public static final List<Item> ALL_POSSIBLE_ITEMS;
static{
List<Item> list =new ArrayList<Item>(10000);
for(int num =0;num <10000;num ++) //magic number: 10000 is result of 10^Item.SIZE
list.add(new Item(num));
ALL_POSSIBLE_ITEMS =Collections.unmodifiableList(list);
}
//数字的各位,从高位到低位排列
int[] bits;
public Item(int num){
bits =new int[SIZE];
for(int index=SIZE-1;num>0;num/=10)
bits[index--] = num%10;
}

@Override
public String toString(){
StringBuilder sb =new StringBuilder(SIZE);
for(int index =0;index< SIZE;index ++)
sb.append(bits[index]);
return sb.toString();
}

/**
用guess去猜word,结果是否返回(b,a)
*/
public static boolean isMatch(Item word,Item guess,int a,int b){
return (getA(word,guess)==a&&getB(word,guess)==b);
}
/**
word 为谜底,guess去猜.
@return guess与word中位置相同数字也相同的个数
*/
public static int getA(Item word,Item guess){
int count =0;
for(int index =0;index<SIZE; index++)
if(word.bits[index]==guess.bits[index]) count ++;
return count;
}

/**
word 为谜底,guess去猜.
@return 猜对的数字个数
*/
public static int getB(Item word,Item guess){
int count =0;
boolean[] flags =new boolean[SIZE];
for(int i =0;i <SIZE;i ++)
for(int j =0;j <SIZE;j ++)
if((!flags[j])&&word.bits[i]==guess.bits[j]){
count ++;
flags[j] =true;
break;
}
return count;
}
}[/code]
Unity技能系统核心:从理论到实践构建可扩展的Buff管理器 本文深入探讨了Unity游戏开发中构建可扩展技能系统的核心——Buff管理器。通过剖析三层架构(数据、逻辑、渲染)与独立组件管理模式,提供了从Buff数据定义、管理器核心实现到可视化编辑器搭建的完整实践方案,旨在解决技能系统维护难题,提升开发效率与代码质量。 阅读详情

相关推荐

halcon3D 点云拟合球体

halon3D 点云拟合球面

weixin_43213429的博客 1641

2007年软件开发者薪资调查报告

回顾过去,展望“钱”景——2007年软件开发者薪资调查报告 http://vipnews.youkuaiyun.com/newscontent.aspx?pointid=2008_02_25_154936518策划、撰文/刘龙静(《程序员》2008年2月刊)每年年初的软件开发者薪资调查报告,已经成为《程序员》杂志的传统,也是众多程序员期待的热点。在如此热闹的2008奥运年当然更

小信念,大梦想 1122

I2S时序及音频驱动

I2S、音频驱动

qq_41882586的博客 3948

选择排序

选择排序

弱爆了的雪饼的博客 589

Frida实战:如何用HashMap.put拦截法快速定位安卓App加密参数(附完整脚本)

本文详细介绍了如何使用Frida拦截HashMap.put方法快速定位安卓App加密参数,提供完整脚本和实战案例。通过动态分析技术,相比传统静态分析大幅提升效率,适用于电商、社交、金融等场景的加密参数定位。

jump7的博客 263

PX4实战(四):PX4 uorb模块详解

本节主要讲解PX4中的uorb消息,主要包括uorb的基本概念使用、PX4内重要的uorb消息、如何自定义uorb消息以及使用uorb消息的注意点等,其中讲解重要uorb消息是为了对PX4内重要数据结构有初步的了解,有助于后期算法理解。uORB(micro Object Request Broker)是PX4中用于模块间通信的轻量级发布-订阅(Publish/Subscribe)机制。模块之间可以通过uORB传递消息,无需直接调用对方函数;提高系统模块化与解耦性;

PX4-SLAM-PNC 1933

用Java-数组 “打擂”

java l--数组擂台赛

不会飞的小飞侠24 1271

高速电路设计必看:同步开关噪声问题解析

数字电路中的同步开关噪声(SSN)问题日益突出,尤其是随着高速器件应用增多。本文分析了地弹和电压弹的产生机理,指出其与电源网络电感、输出驱动电流变化率密切相关。文章详细阐述了地弹参数特征,包括峰值电压、脉冲宽度等关键指标,并探讨了负载电容、信号压摆率等因素对地弹的影响。最后提出系统化的解决方案,涵盖芯片选型、电路设计、PCB布局和后期调试等多个环节,强调通过降低回路电感和控制电流变化率来有效抑制SSN。这些措施需要在性能、成本和复杂度之间取得平衡,为高速数字电路设计提供了重要参考。

一只豌豆象的博客 301

java打擂台算法,打擂台算法.ppt

打擂台算法打擂台算法适用于: 求若干个数中的最大/小值 例题 找两数中的较大者 a=val(inputbox("请输入第一个数")) b=val(inputbox("请输入第二个数")) if a>=b then max=a else max=b endif print max 双分支的写法 (非打擂台的算法) 例题 找两数中的较大者 输入a 输...

weixin_33855603的博客 962

【OpenFOAM】-olaFlow-算例1- baseWaveFlume

算例文件注释--olaFlow-算例1- baseWaveFlume

ou_no的博客 3642

Matlab安装硬件支持包、simulink离线安装硬件支持包安装,离线安装ESP32、stm32等安装包,Are you up-to-date on SoftWare Maintenance?

注意:如果提示出现“没有可从此位置安装的兼容支持包后,这个问题,请查看步骤5,是不是没有按照步骤5进行操作.一般情况下出现“没有可从此位置安装的兼容支持包”后,重新安装选择了默认路径就可以成功。如果不是很清楚,直接安装在默认的文件夹下面,即使这个文件夹下没有matlab相关的文件夹,也要这么下载,没有为什么,切记尽量按默认路径安装,更改下载的路径不成功,别怪我没提醒。:下载到哪里非常重要,如果下载的不是默认的路径下,就需要将其中这个的是这个archives文件夹,连同其他文件一并要复制出来,拷贝到。

pvmsmfchcs的博客 1746

java打擂台排序_C++擂台法排序

#includeusingnamespacestd;voidSort1(inta1[],intn){inti,j;inttemp,max;for(i=0;i#include using namespace std;void Sort1(int a1[],int n){int i,j;int temp,max;for(i=0;imax=i;for(j=0;jif(a1[max] < a1[j]...

weixin_30983563的博客 959

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

java擂台比较,[分享]《程序员》2007第九期算法擂台之JAVA代码

[分享]《程序员》2007第九期算法擂台之JAVA代码[url=http://eastsun.javaeye.com/blog/124477]本题JAVA及C++代码下载[/url]原题:在8*8的棋盘上分布着n个骑士,他们想约在某一格中聚会.骑士每天可以像国际象棋中的马那样移动一次.请你计算n个骑士的最早聚会地点和要走多少天.要求尽早聚会,且n个人走的总步数最少,先到的骑士可以不再移动等待其它骑...

weixin_26801149的博客 164

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

《程序员》2007第九期之算法擂台

原题: 在8*8的棋盘上分布着n个骑士,他们想约在某一格中聚会.骑士每天可以像国际象棋中的马那样移动一次.请你计算n个骑士的最早聚会地点和要走多少天.要求尽早聚会,且n个人走的总步数最少,先到的骑士可以不再移动等待其它骑士. 输入: 从键盘输入n(0<n<=64),然后依次输入n个骑士的初始位置xi,yi(0<=xi,yi<=7) 输出 :以空格分隔的三个整数,分别为聚会点的x,y值,以及要...

JavaSxy的专栏 281

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

《程序员》2007第八期之算法擂台

[color=pink]题目描述(手头没书,不知道有没有记错):[/color][color=green]有v个在一条直线上的村庄,要在其中的p个村庄上修建邮局。每个村庄将会选择离其最近的村庄收发邮件。现在要选择这p个邮局的修建地址,使得这v个村庄到邮局的总路程尽可能少。[/color] [color=orange]输入:首先是两个正整数v,p,表示村庄个数与邮局个数。 然后是v个...

JavaSxy的专栏 252

java程序员入门_Java程序员入门:简介

java程序员入门 背景 Go (通常称为“ Golang”)是一种相当新的编程语言,于2007年首次提出,并于2012年发布了1.0版。它的三位发明者目前都是Google员工,具有令人印象深刻的证书。 肯·汤普森 ( Ken Thompson)是UNIX的传奇之父。 Rob Pike与Thompson一起创建了具有影响力的Plan 9操作系统, Robert Griesemer致力于Java...

danpu0978的博客 386

Java程序员面试宝典

书名:Java程序员面试宝典 作者:欧立奇等编著 来源:电子工业出版社 出版时间:2007年08月 ISBN:9787121045523 定价:46元  第1部分  求职过程古人云:凡事预则立,不预则废。机会都是垂青有准备的人的。为了得到一份满意的工作,大家一定要对整个求职过程有清醒的了解。把能够预见的、必须做

找个地方放东西... 4451

2007年第2周最热网友收藏

http://blog.youkuaiyun.com/zdg/archive/2007/01/15/1483791.aspx 2007年第2周最热网友收藏 C#的四个基本技巧(97),共105人收藏,yanglilibaobao首先收藏 我来做个好人吧,40种网站设计常用技巧(97),共377人收藏,wuzeng2002首先收藏 Visual C#常用函数和方法集汇总(85),共93人收藏,yan...

weixin_30301183的博客 174

2007年上半年 程序员

2007年上半年 程序员 下午试卷 第 1 页 (共 11 页) 全国计算机技术与软件专业技术资格 全全国国计计算算机机技技术术与与软软件件专专业业技技术术资资格格 全国计算机技术与软件专业技术资格( (( (水平 水水平平 水平) )) )考试 考考试试 考试 200 220000 2007 77 7 年上半年 年年上上半半年年 年上半年 程序员 ...

weixin_34352449的博客 439

ac算法 有什么用 Java_程序员必须掌握哪些算法?

算法是程序的灵魂——编程从本质上来说就是算法加数据结构,而算法是编程思想的核心部分。当前程序员的岗位划分逐渐细化。对于研发级程序员来说,掌握算法是完成岗位开发任务的基础,而对于应用级程序员来说,掌握算法是进行岗位升级的重要基础。小编建议程序猿们从以下几个方面审视或提升或入门算法知识结构——基础部分基础编程模型, 包括Java程序的基本结构、原始数据类型与表达式、语句、数组、静态方法、API、字符串...

weixin_39598472的博客 310

java女程序员的出路,持续更新~

他是18罗汉中唯一被马云开除,也是阿里第一位程序员,现在怎样了重新学习JAVA,做一个新的程序员一样。后来他成为阿里巴巴第一批技术专家,技术顾问,著名的JAVA架构师。 2007年阿里巴巴上市以后,马云为了阿里能够做百年企业,做出了一个艰难的决定,让十八罗汉集体辞去创始人职位从零开始,重新竞聘上岗,为阿里巴巴建立"合伙人"制度。 员工:不要说男程序员缺对象,事实公司内网全是女的在征婚交友很多人都觉得程序员都比较宅,每天的工作就是对着电脑敲击着键盘,但不得不承认程序员的收入非常可观,可是不少人却觉得他们

神经网络爱好者 2007

2007:半年的程序员总结

        2008年伊始,伴随着新的一年脚步的来临,觉得有必要总结一下过去半年职业生涯的体会和感触。上个半年,有N多重要的事件,是从来没有遇到过和经历过的。在失败和教训充斥的这个时期,有一些东西还是需要做一下全面的回顾,即作为过去半年成绩的鉴定,也当作一次对未来发展的警醒。        2007年中旬,作为一个刚刚毕业的本科生,我有幸进入了一家知名的外资企业。虽然公司不大,但对于一个计算机

Da Vinci's CyberSpace 1161

2007程序员考试获得省最高分,在此谈谈程序员考试的经验吧

     今天晚上无意发现信息产业部电子教育与考试中心做了统计,关于程序员考试全国前50名排位,我发现还有我的名字呢,后来一看,我还是吉林省最高分呢,后来我就想。既然程序员考试获得省最高分,在此谈谈程序员考试的经验吧.(http://www.ceiaec.org/zgks_ksjbd23.html)     为什么呢,因为我当初考程序员的时候,也到处寻找经验也没找到满意的.所以我就今天就写写吧,希

技术就是个纸老虎---为之,则难者亦易矣;不为,则易者亦难矣。 2536

程序员2007年3月刊上的一道算法题

       晚上无聊的时候把以前的&lt;程序员&gt;杂志拿出来see see,于是就看到了这个算法题.这文章之前也看过,但当时稍微想了一下就溜过去了.今天看的时候突然产生了一些疑问,于是动手写了几行代码测试了下,结果发现文章中的说法并不完全対.       哦,讲了这么久,忘了说这个题在杂志的第65页的第二题.      注意: 原文并没有给出最优策略 的定义,我这儿根据原文的意思考...

JavaSxy的专栏 222

2007年下半年程序员下午试卷

全国计算机技术与软件专业技术资格(水平)考试2007年下半年程序员下午试卷试题一(共15分)阅读以下说明和流程图,填补流程图中的空缺(1)~(5),将解答填入答题纸的对应栏内。[说明]某单位动态收集的数据中常包含重复的数据,所以需要进行处理,使得重复的数据仅出现一次。下面流程图的功能是:在n(n≥1)个数据D1、D2、…、Dn中,选出其中所有不重复的k个数据,置于原来前k个数...

weixin_33973600的博客 363
上一篇: 使用StAX解析XML:使用定制事件和编写 XML
下一篇: 无形的鸟
JavaSxy
博客等级 码龄21年 1粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值