C++にN-Queensを移植

してみた。

昨日のErlang版をほぼストレートに移植。リストは最初STLを使おうとしたけど、再帰と相性が悪いので、自前で定義。リストのdeleteはさぼり。
実行時間を計測してみると、サイズが13で6秒弱くらい。

  • KLIC速す!(ほぼ同じ速度)

再帰が原因かと思い、いくつかループに書き換えてみたりしたが、実行速度はあまり変わらず。リストセルのnewに時間がかかってるんだろうなぁ。
PARDSで並列化しようと思って、とりあえずnewを共有メモリ上に取るよう再定義したら激遅に。 orz
PARDSでの並列化はすぐにはできなさそう。

まぁ、本来C/C++でやるのなら、リストを使わず別のデータ構造でやるんだろうけど。

ソースは以下:

#include <stdio.h>
#include <stdlib.h>

template <class T> class List{
public:
  T value;
  List<T>* next;
};

List<int>* generate(int n){
  if(n > 0) {
    List<int>* c = new List<int>;
    c->value = n; c->next = generate(n-1);
    return c;
  } else {
    return 0;
  }
}

template <class T> List<T>* append(List<T>* a, List<T>* b){
  if(a != 0){
    T h = a->value;
    List<T>* t = a->next;
    List<T>* res = new List<T>;
    res->value = h;
    res->next = append(t,b);
    return res;
  } else {
    return b;
  }
}

List<List<int>*>* qu(List<int>* plu, List<int>* ls, List<int>* lp){
  if(plu == 0) {
    if(ls == 0) {
      List<List<int>*>* res = new List<List<int>*>;
      res->value = lp;
      res->next = 0;
      return res;
    } else {
      return 0;
    }
  } else {
    List<List<int>*>* check(int, int, List<int>*, List<int>*, List<int>*);

    List<int>*  lu = plu->next;
    int p = plu->value;
    List<int>* lr = append<int>(lu, ls);
    List<List<int>*>* ans1 = check(p, 1, lr, lp, lp);
    List<int>* nls = new List<int>;
    nls->value = p;
    nls->next = ls;
    List<List<int>*>* ans2 = qu(lu, nls, lp);
    return append<List<int>*>(ans1, ans2);
  }
}

List<List<int>*>* check(int p, int d, List<int>* l,
			List<int>* qlp0, List<int>* lp){
  if(qlp0 == 0) {
    List<int>* plp = new List<int>;
    plp->value = p;
    plp->next = lp;
    return qu(l,0,plp);
  } else {
    int q = qlp0->value;
    if(q + d == p || q - d == p)
      return 0;
    else{
      List<int>* lp0 = qlp0->next;
      return check(p,d+1,l,lp0,lp);
    }
  }
}

int main(int argc, char* argv[])
{
  if(argc < 2) {
    printf("qu NUM\n");
    exit(0);
  }

  int num = atoi(argv[1]);

  List<int>* gen = generate(num);
  List<List<int>*>* res = qu(gen,0,0);

  int i = 0;
  for(; res != 0; res = res->next, i++){
    /*    List<int>* a = res->value;
      for(; a != 0; a = a->next)
      printf("%d ",a->value);
      printf("\n"); */
  }
  printf("num = %d\n",i);
}