测试大模型八皇后求解ChatGPT、文心一言和ChatGLM3
当前常见的大模型有文心一言、ChatGPT,以及开源的ChatGLM等,今天我们就以八皇后问题来考一下这三个大模型。让我们看看它们的表现吧!我认为c语言对它们可能有点难,就先用lisp试试。虽然很多代码生成并不能一次性成功,但是在多个大模型交叉调试的情况下,还是能满足我们的日常编程需求的。
八皇后问题介绍
八皇后问题是一个古老而著名的数学问题,最早由国际西洋棋棋手马克斯·贝瑟尔于1848年提出。问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
这个问题不仅是一个有趣的谜题,而且是计算机科学中回溯算法的一个经典案例。回溯算法通过逐步构建解决方案,并在发现冲突时回溯到之前的步骤,从而找到所有可能的解决方案。
在八皇后问题中,一种常见的解决方法是使用一个长度为8的数组来表示皇后的位置。数组的每个元素代表一列,其值表示该列上的皇后所在的行号。通过全排列的方式生成所有可能的列排列,并检查每种排列是否满足皇后不互相攻击的条件。
除了全排列解法外,还有其他一些优化方法可以提高求解八皇后问题的效率。例如,可以使用位运算来快速判断两个皇后是否在同一对角线上,或者使用递归和迭代的方法来减少循环次数。
八皇后问题不仅在数学和计算机科学领域具有重要地位,还经常被用作教学和测试算法复杂度的示例。此外,该问题还可以推广为更一般的n皇后摆放问题,即在n×n的棋盘上摆放n个皇后,使其不互相攻击。这个问题也有许多有趣的解法和应用。
大模型介绍
当前常见的大模型有文心一言、ChatGPT,以及开源的ChatGLM等,今天我们就以八皇后问题来考一下这三个大模型。让我们看看它们的表现吧!
我认为c语言对它们可能有点难,就先用lisp试试。
hy lisp代码
请用hy语言写八皇后问题解决的代码
(import itertools *)
(import toolz.itertoolz [first])
(defn solve-n-queens [n]
(defn is-valid [board row col]
(setv queens (map second board))
(and (not (in col queens))
(notany (fn [i] (= 0 (- col (nth queens i)) (- row i))))
(notany (fn [i] (= 0 (+ col (nth queens i)) (- row i))))))
(defn solve [board row]
(if (= row n)
(list board)
(let [cols (range n)]
(filter
(fn [col]
(is-valid board row col))
(map
(fn [col]
(solve (assoc board row col) (+ row 1)))
cols)))))
(first (solve {} 0)))
(print (solve-n-queens 8))
这个(import [itertools *]) 直接有报错,改写成(import itertools *)
报错:NameError: name 'first' is not defined ,发现可以先导入first:(import toolz.itertoolz [first])
报错: (solve (assoc board row col) (+ row 1)))
NameError: name 'assoc' is not defined 先搁置。
本来以为lisp代码是最简单的,但是问题多多,先搁置,看来要调整下阶段工作重心了。
chatgpt的c语言代码
chatgpt的这个c语言的pass
#include <stdio.h>
#include <stdbool.h>
#define N 8
bool isSafe(int board[N][N], int row, int col) {
int i, j;
for (i = 0; i < col; i++)
if (board[row][i])
return false;
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (board[i][j])
return false;
for (i = row, j = col; j >= 0 && i < N; i++, j--)
if (board[i][j])
return false;
return true;
}
bool solveNQUtil(int board[N][N], int col) {
if (col >= N)
return true;
for (int i = 0; i < N; i++) {
if (isSafe(board, i, col)) {
board[i][col] = 1;
if (solveNQUtil(board, col + 1))
return true;
board[i][col] = 0;
}
}
return false;
}
void printSolution(int board[N][N]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
printf("%d ", board[i][j]);
printf("\n");
}
}
void solveNQ() {
int board[N][N] = { {0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0} };
if (solveNQUtil(board, 0) == false) {
printf("Solution does not exist");
return;
}
printSolution(board);
}
int main() {
solveNQ();
return 0;
}
文心一言3.5的c代码
文心一言的刚开始缺失了int j 声明而报错,加上之后,发现结果错误:
#include <stdio.h>
#include <stdbool.h>
#define N 8
bool is_safe(int board[], int row, int col) {
int i;
int j;
// 检查列上是否有冲突
for (i = 0; i < row; i++) {
if (board[i] == col)
return false;
}
// 检查左上方是否有冲突
for (i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (board[i] == j)
return false;
}
// 检查右上方是否有冲突
for (i = row - 1, j = col + 1; i >= 0 && j < N; i--, j++) {
if (board[i] == j)
return false;
}
return true;
}
bool solve_n_queens(int board[], int col) {
// 如果所有列都已经成功放置了皇后
if (col >= N) {
// 输出棋盘状态
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%s ", (board[i] == j) ? "Q " : ". ");
}
printf("\n");
}
printf("\n");
return true; // 找到一个解
}
// 尝试在当前列放置皇后
for (int i = 0; i < N; i++) {
if (is_safe(board, i, col)) {
board[i] = col; // 在 (i, col) 位置放置皇后
// 递归地放置下一列的皇后
if (solve_n_queens(board, col + 1))
return true; // 如果找到一个解,则回溯
// 如果找不到解,则回溯,重置当前位置
board[i] = 0; // 移除 (i, col) 位置的皇后
}
}
// 如果所有行都尝试了但都找不到解,则返回 false
return false;
}
int main() {
int board[N] = {0}; // 初始化棋盘
if (!solve_n_queens(board, 0)) // 从第一列开始放置皇后
printf("Solution does not exist\n");
return 0;
}
运算结果:
./a.out
. . . . . . . Q
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
简单调了下,没有调通。先搁置。
ChatGLM3的c语言代码
刚开始给的代码:
#include <stdio.h>
void print_board(int board[9][9]) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
printf("%d ", board[i][j]);
}
printf("\n");
}
}
int is_safe(int board[9][9], int row, int col) {
for (int i = 0; i < 9; i++) {
if (board[row][i] == col || board[i][col] == col) {
return 0;
}
}
return 1;
}
void solve(int board[9][9], int row, int n) {
if (row == n) {
print_board(board);
printf("\n");
return;
}
for (int col = 0; col < 9; col++) {
if (is_safe(board, row, col)) {
board[row][col] = col + 1;
solve(board, row + 1, n);
board[row][col] = 0;
}
}
}
int main() {
int board[9][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}};
int n = 8;
solve(board, 0, n);
return 0;
}
不明白为什么这里用了9。文心一言说:这段代码的目标是解决九宫数独(Sudoku)问题,但实际上它试图解决的是8皇后问题(N Queens Problem),只是棋盘大小和变量命名有些混淆。数独和8皇后是两个不同的问题,但它们都涉及到在棋盘上放置一些“皇后”或“数字”以避免冲突。
重新问了它问题“再写一个八皇后的实现程序,用c ,注意,不是数独”,这回至少棋盘是对的了
改变了问题策略之后的c代码
#include <stdio.h>
void print_board(int board[8][8]) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printf("%2d ", board[i][j]);
}
printf("\n");
}
}
int is_safe(int board[8][8], int row, int col) {
for (int i = 0; i < 8; i++) {
if (board[i][col] == 1 && row != i) {
return 0;
}
if (board[row][i] == 1 && col != i) {
return 0;
}
}
return 1;
}
void solve(int board[8][8], int row, int n) {
if (row == n) {
print_board(board);
printf("\n");
return;
}
for (int col = 0; col < 8; col++) {
if (is_safe(board, row, col)) {
board[row][col] = 1;
solve(board, row + 1, n);
board[row][col] = 0;
}
}
}
int main() {
int board[8][8] = {{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}};
int n = 8;
solve(board, 0, n);
return 0;
}
拿着这段代码去问文心一言,它说:
这段八皇后问题的代码已经基本正确,但is_safe
函数缺少了斜线方向的冲突检查。在八皇后问题中,我们需要确保新的皇后在放置时不会与任何其他皇后处于同一行、同一列或同一对角线上。
下面是修改后的is_safe
函数,它现在包含了斜线方向的冲突检查:
int is_safe(int board[8][8], int row, int col) {
for (int i = 0; i < 8; i++) {
// 检查列上是否有冲突
if (board[i][col] == 1) {
return 0;
}
// 检查主对角线上是否有冲突
if (row - i >= 0 && col - i >= 0 && board[row - i][col - i] == 1) {
return 0;
}
// 检查次对角线上是否有冲突
if (row - i >= 0 && col + i < 8 && board[row - i][col + i] == 1) {
return 0;
}
}
return 1;
}
将主次对角线的代码修改成文心这段代码,整个程序终于运行成功了!
经过文心一言修改后的完成代码
#include <stdio.h>
void print_board(int board[8][8]) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printf("%2d ", board[i][j]);
}
printf("\n");
}
}
int is_safe(int board[8][8], int row, int col) {
for (int i = 0; i < 8; i++) {
if (board[i][col] == 1 && row != i) {
return 0;
}
if (board[row][i] == 1 && col != i) {
return 0;
}
// 检查主对角线上是否有冲突
if (row - i >= 0 && col - i >= 0 && board[row - i][col - i] == 1) {
return 0;
}
// 检查次对角线上是否有冲突
if (row - i >= 0 && col + i < 8 && board[row - i][col + i] == 1) {
return 0;
}
}
return 1;
}
void solve(int board[8][8], int row, int n) {
if (row == n) {
print_board(board);
printf("\n");
return;
}
for (int col = 0; col < 8; col++) {
if (is_safe(board, row, col)) {
board[row][col] = 1;
solve(board, row + 1, n);
board[row][col] = 0;
}
}
}
int main() {
int board[8][8] = {{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}};
int n = 8;
solve(board, 0, n);
return 0;
}
输出显示:
gcc eightqueen_glm3.c
./a.out
1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 1 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0
总结:
虽然很多代码生成并不能一次性成功,但是在多个大模型交叉调试的情况下,还是能满足我们的日常编程需求的。
调试
hy (import [itertools *]) 直接有报错
(import [itertools *])
Traceback (most recent call last):
File "stdin-0bab587d83cb82a8d732b16c55398dcca4b8b02b", line 1
(import [itertools *])
^
hy.errors.HySyntaxError: parse error for pattern macro 'import': got unexpected token: hy.models.List([
hy.models.Symbol('itertools'),
hy.models.Symbol('*')]), expected: end of input
直接写成(import itertools *)
hy报错:NameError: name 'first' is not defined
发现可以先导入first:(import toolz.itertoolz [first])
hy报错:NameError: name 'assoc' is not defined
(solve (assoc board row col) (+ row 1)))
NameError: name 'assoc' is not defined
先搁置。

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)