编程实现 4 条重写规则,可生成半法式和法式

编程实现 4 条重写规则,有友好的接口。输入任意字后,可生成(1)半法式和(2)法式,并且注明每一步应用了哪一个重写规则。给出源程序和可以执行的程序。

/**
 * @author 康雨城
 * @time 2017/10/17
 * csdn : http://blog.csdn.net/kangyucheng
 * * 运行说明:在任何IDE中创建java Project,然后将创建class命名为Main,将本段代码复制进去即可运行。
 */
import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // 输入字w
        ArrayList<Word> inputList=new ArrayList<Word>();//存储输入字
        ArrayList<Word> subNormalList=new ArrayList<Word>();//存储半法式
        ArrayList<Word> normalList=new ArrayList<>();//存储法式
        //输入任意字
        inputList=getInputList();
        System.out.println("输入数据为:");printList(inputList);
        System.out.println("其中每组数字第一个数字代表下标,第二个数字1代表正字母,-1代表负字母");
        //按照NF1的要求进行排序,得到半法式
        subNormalList=sort(inputList);
        System.out.println("半法式为:");printList(subNormalList);
        //删除违规二元组得到法式
        normalList=subNormalToNormal(subNormalList);
        System.out.println("法式为:");printList(normalList);

    }

    private static ArrayList<Word> getInputList() {
        // 分为随机输入和手动输入两种
        ArrayList<Word> list=new ArrayList<Word>();
        Scanner input =new Scanner(System.in);
        System.out.println("需要手动输入请按y或Y并按回车键,按任意键后并按回车键系统将为您自动输入一组测试数据");
        char c=input.next().charAt(0);
        if(c=='Y'||c=='y'){
            System.out.println("请按以下格式输入数据:  a b 回车。(中间有空格)a为非负数,b为1或-1,当输入0 0时,系统结束输入");
            System.out.println("例如: \n3 1回车\n6 -1回车\n9 -1回车 \n8 -1回车 \n1 -1回车 \n0 0回车\n");
            System.out.println("或者按照以下格式输入:3 1 6 -1 9 -1 8 -1 1 -1 2 1 0 0");
            System.out.println("其中每两个数字一组,每组数字第一个数字代表下标,第二个数字1代表正字母,-1代表负字母");
            while(true){
                int inKey=input.nextInt();
                int inLetter=input.nextInt();
                if(inKey==0&&inLetter==0)break;
                list.add(new Word(inKey,inLetter));
            }
        }
        else{
            //以下数字可计算题目中的(2)
//            list.add(new Word(5,-1));
//            list.add(new Word(3,1));
//            list.add(new Word(7,1));
//            list.add(new Word(9,-1));
//            list.add(new Word(4,-1));
            //以下数字可计算题目中的(3)
//            list.add(new Word(3,-1));
//            list.add(new Word(2,1));
//            list.add(new Word(7,1));
//            list.add(new Word(9,-1));
//            list.add(new Word(4,-1));
//            list.add(new Word(1,-1));
            //以下数字可计算题目中的(4)
//            list.add(new Word(0,1));
//            list.add(new Word(5,-1));
//            list.add(new Word(3,1));
//            list.add(new Word(7,1));
//            list.add(new Word(11,1));
//            list.add(new Word(9,-1));
//            list.add(new Word(4,-1));
//            list.add(new Word(0,-1));
//            list.add(new Word(0,-1));
//            list.add(new Word(0,-1));
//            list.add(new Word(0,-1));

            //以下式子可以实现消除最大违规二元组
            list.add(new Word(7,1));
            list.add(new Word(9,1));
            list.add(new Word(4,-1));
            list.add(new Word(1,-1));
            list.add(new Word(10,-1));
            list.add(new Word(11,1));
            list.add(new Word(13,1));
            list.add(new Word(7,-1));
            list.add(new Word(1,-1));
            list.add(new Word(15,-1));


            //以下狮子可以是反证(4)的例子
//            list.add(new Word(0,1));
//            list.add(new Word(3,-1));
//            list.add(new Word(0,1));
//            list.add(new Word(2,1));
//            list.add(new Word(5,1));
//            list.add(new Word(4,-1));
//            list.add(new Word(3,-1));

        }
        input.close();
        return list;
    }

    private static ArrayList<Word> sort(ArrayList<Word> list) {
        // 冒泡排序的方法写成半法式
        int length=list.size();
        for(int i=0;i<length;i++){
            for(int j=0;j<length-i-1;j++){
                Word word1=list.get(j);
                Word word2=list.get(j+1);
                int key1=word1.getKey();
                int key2=word2.getKey();
                if(word1.getLetter()==Word.POSITIVE
                        &&word2.getLetter()==Word.NEGETIVE){
                    //正字母在左,负字母在右,不交换位置
                }
                else if(word1.getLetter()==Word.NEGETIVE
                        &&word2.getLetter()==Word.POSITIVE){
                    //负字母在左,正字母在右,只有左侧下标小于右侧下标的情况需要交换位置
                    if(word1.getKey()<word2.getKey()){
                        //负字母在左,且负字母下标较小 满足i<k条件 应用R3
                        list.get(j).setKey(key2+1);
                        list.get(j).setLetter(Word.POSITIVE);
                        list.get(j+1).setKey(key1);
                        list.get(j+1).setLetter(Word.NEGETIVE);
                        System.out.print("应用一次R3,得到:");printList(list);
                    }

                    else{
                        //负字母在左,且负字母下标较大 应用 R2
                        list.get(j).setKey(key2);
                        list.get(j).setLetter(Word.POSITIVE);
                        list.get(j+1).setKey(key1+1);
                        list.get(j+1).setLetter(Word.NEGETIVE);
                        System.out.print("应用一次R2,得到:");printList(list);
                    }


                }
                else if(word1.getLetter()==Word.POSITIVE
                        &&word2.getLetter()==Word.POSITIVE){
                    //两个字母都是正字母的情况,只有左侧下标大于右侧下标的情况需要交换位置
                    if(word1.getKey()>word2.getKey()){
                        list.get(j).setKey(key2);
                        list.get(j+1).setKey(key1+1);
                        System.out.print("应用一次R1,得到:");printList(list);
                    }
                }
                else{
                    //两个字母都是负字母的情况,只有左侧下标小于右侧下标的情况需要交换位置
                    if(word1.getKey()<word2.getKey()){
                        list.get(j).setKey(key2+1);
                        list.get(j+1).setKey(key1);
                        System.out.print("应用一次R4,得到:");printList(list);
                    }
                }
            }
        }
        return list;

    }

    private static ArrayList<Word> subNormalToNormal(ArrayList<Word> list) {
        //通过删除违规二元组,将半法式转化为法式
        int maxKeyIndex=getMaxKeyIndex(list);
        int left=maxKeyIndex,right=maxKeyIndex+1;
        while(left>=0&&right<list.size()){
            int pkey=list.get(left).getKey();
            int rkey=list.get(right).getKey();
            if(pkey<rkey){
                right++;
            }
            else if(pkey>rkey){
                left--;
            }
            else{
                int nextPkey=list.get(left+1).getKey();
                int nextRkey=list.get(right-1).getKey();
                if((nextPkey!=pkey+1)&&(nextRkey!=rkey+1)){
                    //已找到最大违规二元组,开始消除
                    System.out.println("找到最大违规二元组:("+pkey+",1) 和 ("+rkey+",-1)");
                    int cr1=0,cr4=0;
                    if(left+1!=right){
                        //违规二元组中间有字母,与中间字母进行交换

                        for(int l=left+1;l<=maxKeyIndex;l++){
                            list.get(l).keyMul();
                            //System.out.print("应用一次R1,得到:");printList(list);
                            cr1++;

                        }
                        for(int r=right-1;r>maxKeyIndex;r--){
                            list.get(r).keyMul();
                            //System.out.print("应用一次R4,得到:");printList(list);
                            cr4++;
                        }
                    }
                    //删除字母,并修改左右指针。
                    list.remove(list.get(left));
                    left--;right--;
                    list.remove(list.get(right));
                    System.out.print("应用"+cr1+"次R1,应用"+cr4+"次R4,应用一次R5,删除了最大违规二元组,得到:");printList(list);
                }
            }
        }
        return list;
    }
    private static int getMaxKeyIndex(ArrayList<Word> list) {
        //获取正字母中下标最大的元素,因为已经是排列完成的半法式,
        //所以,只需要找到两个正字母和负字母的交界即可
        int i=0;
        for(int j=0;j<list.size();j++){
            if(list.get(j).getLetter()==1&&
                    list.get(j+1).getLetter()==-1){
                i=j;
                break;
            }
        }
        return i;
    }

    private static void printList(ArrayList<Word> list) {
        //打印数组
        for(int i=0;i<list.size();i++){
            System.out.print(list.get(i).getKey()+" "+list.get(i).getLetter()  +"    ");
        }

        System.out.println();
    }

}


class Word{
    public static int POSITIVE=1;//正字母
    public static int NEGETIVE=-1;//负字母
    private int key;//下标
    private int letter;//正负字母标识

    public Word(int key, int letter) {
        this.key = key;
        this.letter = letter;
    }

    public Word() {
    }
    public int getKey() {
        return key;
    }
    public void setKey(int key) {
        this.key = key;
    }
    public int getLetter() {
        return letter;
    }
    public void setLetter(int letter) {
        this.letter = letter;
    }
    public void keyMul() {
        this.key--;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

康雨城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值