DeepSeek真有智能吗?

春节期间DeepSeek火起来了,我也蹭了几次热点

  1. DeepSeek能进行逻辑推理吗?
  2. DeepSeek能运行程序吗?
  3. DeepSeek能下围棋吗?
  4. DeepSeek能下围棋吗?(续)

这些例子看上去考察的内容似乎不同,其实根本上是一样的,最终问题都抽象成一个有限状态机(FSM)。
在逻辑推理的例子中,我们看到两个FSM,一个用来判断字符串是否是公式,另外一个用来实现公式的证明。在程序运行的例子中,计算器的描述直接翻译成了一个FSM。在围棋规则的例子中,围棋规则的运行也抽象成了一个FSM。因此,我给了三个例子,其实都可以看成是相同的,就是识别并运行FSM。
个人认为,在某种意义上,智能的一个重要特征,应该是能都识别并运行FSM,也就是将问题抽象成状态集合和规则集合,并能够根据输入,当前状态和相关规则修改状态,生成输出。这个是理性思维的基本特征。如果再推广一点,那就是图灵机的行为了。
我非常想知道,DeepSeek能否理解并执行一个FSM,甚至于要求更高点,说得高大上一点,说得学术化一点,就是问基于大模型的文本生成人工智能是否是图灵机完备的。

那么,DeepSeek能否真的能够识别并运行一个FSM呢?从他的输出上,似乎看到了很明显的能够识别FSM的能力,在执行方面好像也不错。不管是计算器的例子还是围棋规则的例子,让人印象深刻。不过几个例子在执行过程中都或多或少出现了问题。是否所谓的识别了FSM,也不过是一个幻像?所谓识别和执行,都不是生成式大模型内在的能力,只是一种生成出来的幻境?大模型本身根本没有意识到自己识别了一个FSM,并在执行一个FSM,只是他的文本生成的输出让人以为他有这个能力呢。
毕竟只是一个文本生成程序啊,怎么能要求能够识别并执行一个FSM呢?所以识别有些不完备,执行有一些瑕疵,似乎也能接受了吧。
然而,如果这样的话,那在智能方面就存在一个根本性的缺陷了,其实不能称为人工智能,最多只能说具备某种智能表现而已,就像有人号称能够训练狗狗能够做算术题目,其实最终只是针对性训练之后的一种自然反应,称不上真会算算术。
能否改造模型或者运行环境,内置一个FSM的识别和执行机制,这样才真正具备智能的能力。
不管是真有智能也罢,幻像也罢,能够辅助工作也算有很大用途了。我们换个思路,让他来根据给出的规则编出一个软件代码模块,来考察一下代码生成的能力如何。

这次还是以围棋规则为例,来生成一个围棋规则的运行模块程序,试试看DeepSeek的能力。

再来折磨一下DeepSeek吧,启动一个新对话,然后输入:

游戏规则
定义:
1.数字对,是指两个1到9之间的整数组成的有序集合。可与记为(m,n),如果m不等于n,那么认为(m,n)与(n,m)是两个不同的数字对。
2.游戏由两方组成,称为B方和W方,每一方拥有一个集合,称为B集合和W集合,集合中的元素是数字对,游戏开始时B集合和W集合都是空集合。
3.没有出现在B集合和W集合中的所有数字对构成一个K集合
4.两个数字对(m,n)和(a,b),如果n与b一样而且m和a只差1,或者m与a一样而且n和b只差1,称这两个数字对是邻居关系
5.具有邻居关系的两个数字对有粘连关系,如果A与B有粘连关系,B与C也有粘连关系,称A与C也有粘连关系
6.根据粘连关系把B集合和W集合分割成若干子集合,称为粘连块
7.一个粘连块中每个数字对的邻居的集合的并集与K集合的交集称为该粘连块的气集合
8.一个粘连块的气集合中的元素个数称为这个粘连块的气数

规则:
1.由B方先,W方后,交替选择一个K中的数字对加入到自己一方的集合中。
2.选择的~数字对加入自己一方的集合后可能导致双方的粘连块有变化,如果变化后的某个粘连块的气数变为0,如果这个粘连块是对方的,可以将这个粘连块中的所有数字对从对方数字对集合中删除,
3.如果选择的数字对不能使对方的某个粘连块气数变成0,反而使自己一方的某个粘连块气数变成0,那这个数字对就不能选择。
4,某方选择的数字对导致对方被删除的数字对只有一个,这个数字对下一次对方不能选择5,直到一方无法选择合法的数字对,此时游戏结束6,结束是计算B集合中的数字对个数,收集B集合中所有数字对的邻居集合与K集合的交集中的数字对个数,两个数字加起来,称为B方的地盘数Bn,对W方也按相同的规则统计出W方地盘数Wn,如果Bn-Wn>3则称B方赢,否则称W方赢

游戏规则解析

定义
  1. 数字对:由两个1到9之间的整数组成的有序集合,记为(m,n)。若m≠n,则(m,n)与(n,m)视为不同的数字对。
  2. 游戏双方:B方和W方,各自拥有一个集合(B集合和W集合),初始为空。
  3. K集合:未出现在B集合和W集合中的所有数字对。
  4. 邻居关系:两个数字对(m,n)和(a,b),若n=b且|m-a|=1,或m=a且|n-b|=1,则称它们为邻居关系。
  5. 粘连关系:若A与B有邻居关系,B与C也有邻居关系,则A与C有粘连关系。
  6. 粘连块:根据粘连关系将B集合和W集合分割成的若干子集合。
  7. 气集合:一个粘连块中所有数字对的邻居集合的并集与K集合的交集。
  8. 气数:气集合中的元素个数。
游戏规则
  1. 轮流选择:B方先手,W方后手,交替从K集合中选择一个数字对加入自己的集合。
  2. 粘连块变化:选择的数字对加入后,可能导致双方的粘连块变化。若某粘连块的气数变为0,且该粘连块属于对方,则将该粘连块中的所有数字对从对方集合中删除。
  3. 选择限制:若选择的数字对不能使对方的粘连块气数变为0,反而使自己的粘连块气数变为0,则该数字对不可选择。
  4. 删除限制:若某方选择的数字对导致对方被删除的数字对只有一个,则对方下一次不能选择该数字对。
  5. 游戏结束:当一方无法选择合法的数字对时,游戏结束。
  6. 胜负判定
  • 计算B集合中的数字对个数。
  • 收集B集合中所有数字对的邻居集合与K集合的交集中的数字对个数。
  • 将这两个数字相加,称为B方的地盘数Bn。
  • 对W方按相同规则统计出W方的地盘数Wn。
  • 若Bn - Wn > 3,则B方赢;否则,W方赢。

示例

假设游戏进行到某一步,B集合和W集合如下:

  • B集合:{(1,2), (2,2)}
  • W集合:{(2,3), (3,3)}
  • K集合:{(1,1), (1,3), (2,1), (3,2), (3,1)}

粘连块分析

  • B方的粘连块:{(1,2), (2,2)}
  • W方的粘连块:{(2,3), (3,3)}

气集合分析

  • B方的粘连块的气集合:{(1,1), (1,3), (2,1), (3,2), (3,1)} ∩ K集合 = {(1,1), (1,3), (2,1), (3,2), (3,1)}
  • W方的粘连块的气集合:{(2,2), (3,2), (3,1)} ∩ K集合 = {(2,1), (3,2), (3,1)}
    气数
  • B方的粘连块气数:5
  • W方的粘连块气数:3
    在这里插入图片描述

选择数字对

  • 若B方选择(2,1)加入B集合,可能导致W方的粘连块气数减少,若气数变为0,则W方的粘连块将被删除。

结论

通过以上规则和示例,玩家可以逐步掌握游戏策略,合理选择数字对以增加自己的地盘数,同时减少对方的地盘数,最终赢得比赛。

这次好像又不一样了,举的例子中K集合似乎不对,好担心他出问题诶。为何每次运行结果都不一样呢?按说每次开启新对话,他应该忘记了前面所有的缓冲信息才是,每次都不一样,让人担惊受怕诶。
仔细看看,气集合和气都没算对诶,

  • B方的粘连块的气集合:{(1,1), (1,3), (2,1), (3,2), (3,1)} ∩ K集合 = {(1,1), (1,3), (2,1), (3,2), (3,1)}
    (3,1)连邻居都不是,怎么变成气集合中的一个了?
  • W方的粘连块的气集合:{(2,2), (3,2), (3,1)} ∩ K集合 = {(2,1), (3,2), (3,1)}
    (2,1)不在W方的粘连块气集合中,求个交集还多出来了。看来我想多了,集合交集也能算错,不指望他了,这次来的不知道是个什么样的新萌,都懒得提醒他。

不管怎么说,继续让它干活,这次来点新的。

请生成一个c语言模块,提供下面的功能:
1.定义一个游戏的上下文数据结构,能够记录游戏所需要的数据,包括B集合,W集合,上一次游戏方的选择是否导致只有一个数字对被删除,如果是,还得记录被删除的数字对,该数字对不允许当前游戏方选择。还应该记录当前轮到B方还是W做选择。
2.提供接口接受游戏方选择,应该能够判断选择是否合法,如果合法,则更新游戏上下文中的状态
3.提供B集合,W集合,K集合等内部数据的查询接口
4.提供游戏是否结束的判断接口
5.提供游戏是否结束时判断输赢的接口
6.提供双方粘连块和对应的气数的计算查询接口

以下是一个C语言模块的实现,提供了您所要求的功能。该模块定义了游戏上下文数据结构,并提供了相应的接口来操作和查询游戏状态。

C语言模块代码

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

#define MAX_PAIRS 81 // 最大数字对数量 (9x9)
// 定义数字对结构
typedef struct {    
     int m;    
     int n;
} Pair;
// 定义游戏上下文结构
typedef struct {    
     Pair B_set[MAX_PAIRS]; // B集合    
     int B_count;           // B集合中数字对的数量    
     Pair W_set[MAX_PAIRS]; // W集合    
     int W_count;           // W集合中数字对的数量    
     Pair last_deleted;     // 上一次被删除的数字对    
     bool last_deleted_valid; // 上一次是否有数字对被删除        
     bool is_B_turn;        // 当前是否是B方的回合
} GameContext;

// 初始化游戏上下文
void init_game(GameContext *ctx) {    
  ctx->B_count = 0;    
  ctx->W_count = 0;    
  ctx->last_deleted_valid = false;    
  ctx->is_B_turn = true; // B方先手
}

// 判断数字对是否在集合中
bool is_pair_in_set(Pair p, Pair set[], int count) {    
  for (int i = 0; i < count; i++) {        
    if (set[i].m == p.m && set[i].n == p.n) {            
      return true;        
    }    
  }    
  return false;
}

// 判断数字对是否在K集合中
bool is_pair_in_K(Pair p, GameContext *ctx) {    
  return !is_pair_in_set(p, ctx->B_set, ctx->B_count) &&           !is_pair_in_set(p, ctx->W_set, ctx->W_count);
}

// 判断两个数字对是否是邻居关系
bool is_neighbor(Pair p1, Pair p2) {    
  return (p1.m == p2.m && abs(p1.n - p2.n) == 1) ||           (p1.n == p2.n && abs(p1.m - p2.m) == 1);
}

// 计算粘连块的气数
int calculate_liberty(Pair block[], int block_count, GameContext *ctx) {    
  Pair neighbors[MAX_PAIRS * 4]; // 每个数字对最多有4个邻居    
  int neighbor_count = 0;    
  // 收集所有邻居    
  for (int i = 0; i < block_count; i++) {        
    Pair p = block[i];        
    Pair potential_neighbors[4] = {            
      {p.m - 1, p.n}, 
      {p.m + 1, p.n}, 
      {p.m, p.n - 1}, 
      {p.m, p.n + 1}        
    };        
    for (int j = 0; j < 4; j++) {            
      if (potential_neighbors[j].m >= 1 && potential_neighbors[j].m <= 9 &&                potential_neighbors[j].n >= 1 && potential_neighbors[j].n <= 9) {                
        neighbors[neighbor_count++] = potential_neighbors[j];            
      }        
    }    
  }    
  // 去重并统计在K集合中的邻居   
  int liberty_count = 0;    
  for (int i = 0; i < neighbor_count; i++) {        
    if (is_pair_in_K(neighbors[i], ctx)) {          
      liberty_count++;        
    }    
  }    
  return liberty_count;
}

// 判断选择是否合法
bool is_legal_move(Pair p, GameContext *ctx) {    
  // 检查是否在K集合中    
  if (!is_pair_in_K(p, ctx)) {        
    return false;    
  }    
  // 检查是否是被禁止的选择    
  if (ctx->last_deleted_valid && p.m == ctx->last_deleted.m && p.n == ctx->last_deleted.n) {     
     return false;    
  }    
// 检查是否会导致自己的粘连块气数为0    
// 这里需要实现粘连块的检测逻辑    
// 由于实现较复杂,暂留空    
  return true;
}
// 更新游戏状态
void make_move(Pair p, GameContext *ctx) {    
  if (!is_legal_move(p, ctx)) {        
    printf("非法选择!\n");        
    return;    
  }   
   // 添加到当前方的集合    
   if (ctx->is_B_turn) {        
     ctx->B_set[ctx->B_count++] = p;    
   } else {        
     ctx->W_set[ctx->W_count++] = p;    
   }    
   // 更新上一次被删除的数字对    
   ctx->last_deleted_valid = false; 
   // 暂时假设没有删除    
   // 切换回合    
   ctx->is_B_turn = !ctx->is_B_turn;
 }
 // 查询B集合
 void query_B_set(GameContext *ctx) {    
   printf("B集合: ");    
   for (int i = 0; i < ctx->B_count; i++) {        
     printf("(%d,%d) ", 
     ctx->B_set[i].m, ctx->B_set[i].n);    
   }    
   printf("\n");
}
// 查询W集合
void query_W_set(GameContext *ctx) {    
  printf("W集合: ");    
  for (int i = 0; i < ctx->W_count; i++) {        
    printf("(%d,%d) ", ctx->W_set[i].m, ctx->W_set[i].n);    
  }    
  printf("\n");
}

// 查询K集合
void query_K_set(GameContext *ctx) {    
  printf("K集合: ");    
  for (int m = 1; m <= 9; m++) {        
    for (int n = 1; n <= 9; n++) {            
      Pair p = {m, n};            
      if (is_pair_in_K(p, ctx)) {                
        printf("(%d,%d) ", m, n);            
      }        
    }    
  }    
  printf("\n");
}

// 判断游戏是否结束
bool is_game_over(GameContext *ctx) {    
  // 遍历K集合,检查是否还有合法选择    
  for (int m = 1; m <= 9; m++) {        
    for (int n = 1; n <= 9; n++) {            
      Pair p = {m, n};            
      if (is_pair_in_K(p, ctx) && is_legal_move(p, ctx)) {      
        return false;            
      }        
    }    
  }    
  return true;
}

// 判断输赢
void judge_winner(GameContext *ctx) {    
  int Bn = ctx->B_count;    
  int Wn = ctx->W_count;    
  // 计算B方的地盘数    
  for (int i = 0; i < ctx->B_count; i++) {        
    Pair p = ctx->B_set[i];        
    Pair neighbors[4] = {            
      {p.m - 1, p.n}, 
      {p.m + 1, p.n}, 
      {p.m, p.n - 1}, 
      {p.m, p.n + 1}        
    };        
    for (int j = 0; j < 4; j++) {            
      if (is_pair_in_K(neighbors[j], ctx)) {                
        Bn++;            
      }
    }    
  }    
  // 计算W方的地盘数    
  for (int i = 0; i < ctx->W_count; i++) {        
    Pair p = ctx->W_set[i];        
    Pair neighbors[4] = {            
      {p.m - 1, p.n}, 
      {p.m + 1, p.n}, 
      {p.m, p.n - 1}, 
      {p.m, p.n + 1}        
    };        
    for (int j = 0; j < 4; j++) {           
      if (is_pair_in_K(neighbors[j], ctx)) {                
        Wn++;            
      }        
    }    
  }    
  // 判断胜负    
  if (Bn - Wn > 3) {        
    printf("B方赢!\n");    
  } else {        
    printf("W方赢!\n");    
  }
}

// 查询粘连块和气数
void query_blocks_and_liberties(GameContext *ctx) {    
  // 这里需要实现粘连块的检测逻辑    
  // 由于实现较复杂,暂留空    
  printf("粘连块和气数查询功能暂未实现。\n");
}

int main() {    
  GameContext ctx;    
  init_game(&ctx);    
  // 示例操作    
  Pair p1 = {1, 1};    
  Pair p2 = {1, 2};    
  Pair p3 = {2, 2};    
  make_move(p1, &ctx);    
  make_move(p2, &ctx);    
  make_move(p3, &ctx);    
  query_B_set(&ctx);    
  query_W_set(&ctx);    
  query_K_set(&ctx);    
  if (is_game_over(&ctx)) {        
    judge_winner(&ctx);    
  }    
  return 0;
}


功能说明

  1. 游戏上下文数据结构
  • 使用GameContext结构体记录B集合、W集合、上一次被删除的数字对、当前回合等信息。
  1. 选择接口
  • make_move函数接受一个数字对,判断其合法性并更新游戏状态。
  1. 查询接口
  • query_B_setquery_W_setquery_K_set分别用于查询B集合、W集合和K集合。
  1. 游戏结束判断
  • is_game_over函数检查游戏是否结束。
  1. 胜负判断
  • judge_winner函数计算双方的地盘数并判断胜负。
  1. 粘连块和气数查询
  • query_blocks_and_liberties函数暂未实现,需补充粘连块的检测逻辑。

注意事项

  • 粘连块的检测逻辑较为复杂,需要进一步实现。
  • 游戏规则中的删除逻辑(如气数为0时删除对方粘连块)尚未完全实现。
  • 可以通过扩展和优化代码来完善功能。

评价:
应该说,我讲了一个这么抽象的要求,DeepSeek能够生成这样的代码,应该很满意了。虽然其中的关键函数没有给出实现,但是已经没有难度了。
专业人士要想把自己的想法变成能够运行的程序,其实要求是非常高的。如果配一个专业的程序员,又存在一个交流的问题。专业人士要把事情给程序员讲清楚,本来就是一个非常困难的事情,往往会带来理解上的不同,双方对讨论的目标的理解总是有区别。
哪怕是专业的程序员,总是比较讨厌精力被大部分花费在一些编程的细节中,这样的工作非常耗精力,DeepSeek有希望把他们从繁琐的编程细节中解放出来,通过DeepSeek的辅助,生成规范的代码,程序员只需要实现关键模块(着这部分估计都能够通过交互自动生成其中很多代码)。
应该说,目前的DeepSeek只能做辅助,但是这样已经很不错了。为每个程序员配个人当编程秘书不大可能,但是配个DeepSeek作为专职秘书,还是可能的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

饶先宏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值