一行Java代码八皇后

一行代码八皇后

其实是标题党,准确的说是在一定条件只需要一行。

先上代码:

count(accumulate((r, i) -> flatmap((List ps0) -> map(y -> cons(y, ps0), filter(y0 -> y((TriFunction, Integer, Integer, Boolean> fn) -> (List ps, Integer y, Integer gap) -> ps == null || !(car(ps) == y || car(ps) == y + gap || car(ps) == y - gap) && fn.apply(cdr(ps), y, gap + 1)).apply(ps0, y0, 1), range(1, 8))), r), list((List) null), range(1, 8)));

当然他是不能独立运行的,完整代码:https://gist.github.com/ezksd/07a91873fcacdf66e44ed7aca7171b17

首先要定义一些辅助的数据结构

类似scheme里的pair和list。

class Pair {
    A a;
    B b;
    Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }
}

class List extends Pair> {
    List(E e, List eList) {
        super(e, eList);
    }
}

@FunctionalInterface:用来表示lambda表达式的类型,

interface TriFunction{
    R apply(A a, B b, C c);
}

interface RecurFunc extends Function, T> {}

function包里面只有单参数的Function,两个参数的BiFunction,现在我们需要一个三参数的。三个参数也可以科里化成单参数的,考虑到代码长度(已经很长了)的原因就直接加了这个东西。

RecurFunc是y combinator里面用来表达一个高阶函数,apply自己,返回目标函数。

因为java的定义不能递归(不支持letrec),比如你不能写int i = i + 1,而且lambda表达式不借助其他手段不能递归调用自己,y combinator就是这个其他手段。

关于y combinator,可以看看Y combinator 推导过程 ,抄袭自The Y Combinator。

然后是一些工具函数

package core;


import java.util.function.BiFunction;
import java.util.function.Function;

public class EightQueens {

    static  A car(Pair pair) {
        return pair.a;
    }

    static  B cdr(Pair pair) {
        return pair.b;
    }

    static  List cons(E item, List list) {
        return new List<>(item, list);
    }

    static  List list(E... items) {
        List r = null;
        for (int i = items.length - 1; i >= 0; i--) {
            r = new List<>(items[i], r);
        }
        return r;
    }

    static  List append(List l1, List l2) {
        return l1 == null ? l2 : cons(car(l1), append(cdr(l1), l2));
    }

    static  R apply(Function f, T t) {
        return f.apply(t);
    }

    static  R apply(BiFunction op, T first, U second) {
        return op.apply(first,second);
    }


    static  List map(Function f, List list) {
        return list == null ? null : cons(apply(f, car(list)), map(f, cdr(list)));
    }

    static  List filter(Function pred, List list) {
        return isNull(list)?null:apply(pred, car(list)) ? cons(car(list), filter(pred, cdr(list))) : filter(pred, cdr(list));
    }


    static  R accumulate(BiFunction op, R initial, List list) {
        return list == null ? initial : accumulate(op, apply(op, initial, car(list)), cdr(list));
    }

    static  List flatmap(Function> op, List list) {
        return accumulate(EightQueens::append, null, map(op, list));
    }

    static List range(int start,int end){
        return start>end?null:cons(start, range(start + 1, end));
    }


    static  TriFunction y(Function, TriFunction> x) {
        RecurFunc> prod = f -> x.apply((a,b,c) -> f.apply(f).apply(a,b,c));
        return prod.apply(prod);
    }

    static int count(List list){
        return isNull(list)? 0:1 + count(cdr(list));
    }


    static boolean isNull(Object o) {
        return o == null;
    }

}



是的,你没有看错,虽然标题是一行Java代码,辅助函数却有这么长。但是如果你仔细看看,这些辅助函数并不是为写八皇后特化的,或者说把复杂的东西包起来。

具体这行代码是什么意思,可以看看[用Stream API写八皇后](用Stream API写八皇后) ,其实是一个东西。

你可能感兴趣的:(一行Java代码八皇后)