求小明正确的四位手机密码

小学生题目:
小明五次输入四位数的手机密码均错误,但是每次输入的密码中都有两位数字正确,且输入的数字的位置都不正确。求小明正确的四位手机密码。

五次手机密码分别是:
6087 5173 1358 3825 2531

解:
使用排除法推导:

首先,在小明输入的数字中:12356780这八个数字中,选择两个数字,顺向推导。如果推导不顺利,最多需要推导8*8=64次。

…………省略不正确的推导过程。以下是正确的推导过程:

1、若正确的数字为5和3,
由1358 与2531 >>> 5与3在第1位与第4位;
由5173与3825 >>> 5与3在第2位与第3位;
互相矛盾——故正确的密码不包含3和5;

2、因为5与3是错误的数字,
由1358 >>> 8与1是正确的数字,
由2531 >>> 2与1是正确的数字,
由3825 >>> 8与2是正确的数字,
由5173 >>> 7和1是正确的数字,

故知,正确的密码包含的数字为 1,2,7,8。

3、正确的数字为 1,2,7,8
由6087 >>> 8不在第3位,7不在第4位,
由5173 >>> 1不在第2位,7不在第3位,
由1358 >>> 1不在第1位,8不在第4位,
由3825 >>> 8不在第2位,2不在第3位,
由2531 >>> 2不在第1位,1不在第4位,

综合:
1不在第2位 &&
1不在第1位 &&
1不在第4位 ——–故1只能是第3位

8不在第2位 &&
8不在第3位 &&
8不在第4位 ——–故8只能是第1位

7不在第4位 &&
7不在第3位 ——–故7可能在第1位和第2位
又由于第1位为8,故7只能在第2位

2不在第1位 &&
2不在第3位 ——–故2可能在第4位和第2位
又由于第2位为7,故2只能在第4位。

3、最后:
1只能是第3位
8只能是第1位
7只能在第2位
2只能在第4位

知正确的密码:8712

求得晕乎乎。至于为什么一开始就选中正确的数字进行推导,或许有更好的办法,但是我不知道。也许数学就是需要一个具有灵感的脑袋。

很明显,我灵感细胞缺乏,于是动手编程求解:

package test;

import java.util.ArrayList;
import java.util.Iterator;

public class NumsTest {

    public static void main(String[] args) {
        Work work = new Work();
        work.working();
    }

    public static class Work{

        private int[] a = {6,0,8,7};
        private int[] b = {5,1,7,3};
        private int[] c = {1,3,5,8};
        private int[] d = {3,8,2,5};
        private int[] e = {2,5,3,1};

        //不存在数字4,9,遇到4,9时忽略

        private ArrayList<int[]>lists;

        public Work() {
            lists = new ArrayList<int[]>();
            lists.add(a);
            lists.add(b);
            lists.add(c);
            lists.add(d);
            lists.add(e);
        }

        public void working(){

            for (int i = 0; i < 10000; i++) {
                int num4 = i%10000/1000;
                int num3 = i%1000/100;
                int num2 = i%100/10;
                int num1 = i%10/1;

                boolean flag = false;
                int[] nums = new int[]{num4,num3,num2,num1};
                //不存在数字4,9,遇到4,9时忽略
                for (int j = 0; j < nums.length; j++) {
                    int k = nums[j];
                    if (k==4||k==9) {
                        flag = true;
                    }
                }

                if (flag) continue;//跳到生成数字的下一次i+1循环

                flag = jobing(nums);
                if (flag) {
                    System.out.println("正确的密码:\n"+num4+""+num3+""+num2+""+num1);
                }
            }

        }

        /**
         * @param num 遍历生成的所有4位数字组合密码。用于比对小明五次输入的密码。
         * @return 当5次输入均符合条件:只有两个正确,且所有数字位置都不正确时返回true,表示得到了正确密码。
         */
        private boolean jobing(int[] num){
            int count=0;
            for (Iterator<int[]> iterator = lists.iterator(); iterator.hasNext();) {
                int[] is = (int[]) iterator.next();
                boolean flag = doJob(num,is);
                if (flag) {
                    count++;
                }
            }
            if (count==lists.size()) {
                return true;
            }
            return false;

        }
        /**
         * @param ns 生成的表示密码所有4位组合的数组,范围为0000~9999
         * @param ms 小明每次输入的密码数组
         * @return true表示小明一次输入的密码和遍历生成的可能密码比对成功,符合要求
         */
        private boolean doJob(int[] ns,int[] ms) {
            /*
             * 1、遍历求出包含正确数字的可能密码的数字串
             *小明输入的密码每次都只有两个正确。
             *当4位组合密码与小明输入的密码有两个数相同时,将可能数字串与其余四个输入比较
             *
             *ns=8721-8712---ms=3825,数字所有位置都不对
             *第一位8--3,特点:第i位互不相同
             *6655--3825
             */
            int count=0;//用于记录数字组合中包含多少个小明输入的数字。包含2个即可能包含了正确密码
            int coun=0;//用于记录有多少个数字位置不正确,所有第i数字不相等,即表示位置不正确。

            for (int i = 0; i < ns.length; i++) {
                int n = ns[i];

                for (int k = 0; k < ms.length; k++) {
                    int m = ms[k];

                    if ( n==m ) {//存在相同数字,计数。
                        count++;                            
                    }
                }

                if (ns[i]!=ms[i]) {//当第i位互不相同,计数
                    coun++;
                }

            }

            if (count==2 && coun==ns.length) {
                //当只有两个数字正确,且所有数字位置都不正确时,一次比较成功,
                //需比较5次(小明输入5次密码)
                return true;
            }

            return false;
        }

    }
}


运行结果:

这里写图片描述

编程思路1:

这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值