找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 18132|回复: 8

不限语言解决“约瑟夫问题”

[复制链接]
发表于 2019-3-3 15:58:49 | 显示全部楼层 |阅读模式
本帖最后由 老刘1号 于 2019-4-22 13:58 编辑

其实是个老算法题了,今天看到群里有人提起,就来发个帖子,

据说著名犹太历史学家 Josephus 有过以下的故事:在罗马人占
领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,
39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方
式:41 个人围成一个圆圈,由第 1 个人开始报数,报数到第 3 个人,
该人就必须自杀,然后再由下一个重新报数,报数到的第 3 个人,该
人又自杀...直到所有人都自杀身亡为止,然而 Josephus 和他的朋友
并不想遵从。
一开始有 i 个人,数 j 去 1,最后剩余 k 个人。首先从一个人开
始,越过 j-1 个人,并杀掉第 j 个人;接着再越过 j-1 个人,并杀掉
第 j 个人...这个过程沿着圆圈一直进行,直到最终只剩下 k 个人,这
k 个人就可以继续活着。问题是,给定了 i、j、k 值,一开始要站在
什么地方才能避免被处决?聪明的Josephus要他的朋友先假装遵从,
他将朋友与自己安排在第 16 个与第 31 个位置,于是逃过了这场死亡
游戏。


汇编-一维数组版
  1. ;约瑟夫问题(一维数组) Algo
  2. ;Code By 老刘
  3. ;环境:MASM32 SDK
  4. ;编译指令:ml /coff 约瑟夫问题(一维数组).asm /link /subsystem:console
  5. ;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。
  6. ;参数最大值:999999。
  7. ;参考:MHL批处理标准教程之约瑟夫问题。


  8. Include masm32rt.inc
  9. Main Proto

  10. .Data?
  11.         bBuffer DB 999999 Dup (?)
  12.         dwAll DD ?
  13.         dwPersist DD ?
  14.         bBuffer2 DB 11 Dup (?)
  15.         dwCrLfZero DD ?
  16.         dwJumpPlusOne DD ?
  17. ;End Data?

  18. .Code
  19.         Main Proc
  20.                 ;获得参数
  21.                 Invoke ArgClC,1,Offset bBuffer2
  22.                 Sub Esp,4
  23.                 Invoke atodw_ex,Offset bBuffer2
  24.                 Add Esp,4
  25.                 Mov dwAll,Eax
  26.                 Invoke ArgClC,2,Offset bBuffer2
  27.                 Sub Esp,4
  28.                 Invoke atodw_ex,Offset bBuffer2
  29.                 Add Esp,4
  30.                 Mov dwPersist,Eax
  31.                 Invoke ArgClC,3,Offset bBuffer2
  32.                 Sub Esp,4
  33.                 Invoke atodw_ex,Offset bBuffer2
  34.                 Add Esp,4
  35.                 Mov dwJumpPlusOne,Eax
  36.                
  37.                 ;开始标记
  38.                 Lea Ebx,bBuffer
  39.                 Add Ebx,dwAll
  40.                 Mov Edx,dwAll
  41.                 Lea Esi,bBuffer
  42.                 Mov Edi,Esi
  43.                 Xor Eax,Eax
  44.                 .While Edx != dwPersist
  45.                         Mov Ecx,dwJumpPlusOne
  46.                         .Repeat
  47.                                 LodSB
  48.                                 Add Ecx,Eax
  49.                                 .If Esi == Ebx
  50.                                         Mov Esi,Edi
  51.                                 .EndIf
  52.                         .UntilCxZ
  53.                         .If Esi == Edi
  54.                                 Mov Byte Ptr [Ebx-1],1
  55.                         .Else
  56.                                 Dec Esi
  57.                                 Mov Byte Ptr [Esi],1
  58.                                 Inc Esi
  59.                         .EndIf
  60.                         Dec Edx
  61.                 .EndW
  62.                
  63.                 ;输出
  64.                 Mov dwCrLfZero,000D0AH
  65.                 Xor Ecx,Ecx
  66.                 Lea Esi,bBuffer
  67.                 Dec Esi
  68.                 .While Ecx != dwAll
  69.                         Inc Ecx
  70.                         .If Byte Ptr [Esi+Ecx] == 0
  71.                                 Pushad
  72.                                 Invoke dw2a,Ecx,Offset bBuffer2
  73.                                 Invoke StdOut,Offset bBuffer2
  74.                                 Invoke StdOut,Offset dwCrLfZero
  75.                                 Popad
  76.                         .EndIf
  77.                 .EndW
  78.                
  79.                 Ret
  80.         Main EndP
  81.        
  82.         Start:
  83.                 Call Main
  84.                 Invoke ExitProcess,NULL
  85.         End Start
  86. End
复制代码
汇编-单向循环链表版
  1. ;约瑟夫问题(单向循环链表) Algo
  2. ;Code By 老刘
  3. ;环境:MASM32 SDK
  4. ;编译指令:ml /coff 约瑟夫问题(单向循环链表).asm /link /subsystem:console
  5. ;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。
  6. ;参数最大值:1227。
  7. ;参考:MHL批处理标准教程之约瑟夫问题。


  8. Include masm32rt.inc
  9. Main Proto

  10. OneWayLinkedList Struct
  11.         Data DWord ?
  12.         Next DWord ?
  13. OneWayLinkedList EndS

  14. .Data?
  15.         dwAll DD ?
  16.         dwPersist DD ?
  17.         dwJump DD ?
  18.         bBuffer2 DB 11 Dup (?)
  19.         dwCrLfZero DD ?
  20.         dwLinkedListHead DD ?
  21. ;End Data?

  22. .Code
  23.         Main Proc
  24.                 ;获得并处理参数
  25.                 Invoke ArgClC,1,Offset bBuffer2
  26.                 Sub Esp,4
  27.                 Invoke atodw_ex,Offset bBuffer2
  28.                 Add Esp,4
  29.                 Mov dwAll,Eax
  30.                 Invoke ArgClC,2,Offset bBuffer2
  31.                 Sub Esp,4
  32.                 Invoke atodw_ex,Offset bBuffer2
  33.                 Add Esp,4
  34.                 Mov dwPersist,Eax
  35.                 Invoke ArgClC,3,Offset bBuffer2
  36.                 Sub Esp,4
  37.                 Invoke atodw_ex,Offset bBuffer2
  38.                 Add Esp,4
  39.                 Dec Eax
  40.                 Mov dwJump,Eax
  41.                
  42.                 ;创建链表
  43.                 Assume Ebx:Ptr OneWayLinkedList
  44.                 Assume Eax:Ptr OneWayLinkedList
  45.                 Invoke Alloc,SizeOf OneWayLinkedList
  46.                 Mov dwLinkedListHead,Eax
  47.                 Mov Ecx,dwAll
  48.                 Dec Ecx
  49.                 Xor Edx,Edx
  50.                 .Repeat
  51.                         Mov Ebx,Eax
  52.                         Inc Edx
  53.                         Push Ecx
  54.                         Push Edx
  55.                         Invoke Alloc,SizeOf OneWayLinkedList
  56.                         Pop Edx
  57.                         Pop Ecx
  58.                         Mov [Ebx].Next,Eax
  59.                         Mov [Ebx].Data,Edx
  60.                 .UntilCxZ
  61.                 Mov Ebx,Eax
  62.                 Inc Edx
  63.                 Push dwLinkedListHead
  64.                 Pop [Ebx].Next        ;指向链表结点1
  65.                 Mov [Ebx].Data,Edx
  66.                 ;此时Ebx指向尾结点
  67.                
  68.                 ;开始标记
  69.                 Mov Edx,dwAll
  70.                 .While Edx != dwPersist
  71.                         Mov Ecx,dwJump
  72.                         .If Ecx != 0
  73.                                 .Repeat
  74.                                         Mov Ebx,[Ebx].Next
  75.                                 .UntilCxZ
  76.                         .EndIf
  77.                         Mov Eax,[Ebx].Next
  78.                         Mov Ecx,[Eax].Next
  79.                         Mov [Ebx].Next,Ecx
  80.                         Push Edx
  81.                         Invoke Free,Eax
  82.                         Pop Edx
  83.                         Dec Edx
  84.                 .EndW
  85.                
  86.                 ;遍历链表并输出
  87.                 Mov dwCrLfZero,000D0AH
  88.                 Mov Ecx,Ebx
  89.                 .Repeat
  90.                         Pushad
  91.                         Invoke dw2a,[Ebx].Data,Offset bBuffer2
  92.                         Invoke StdOut,Offset bBuffer2
  93.                         Invoke StdOut,Offset dwCrLfZero
  94.                         Popad
  95.                         Mov Ebx,[Ebx].Next
  96.                 .Until Ebx == Ecx
  97.                 Assume Ebx:Nothing
  98.                 Assume Eax:Nothing
  99.                
  100.                 Ret
  101.         Main EndP
  102.        
  103.         Start:
  104.                 Call Main
  105.                 Invoke ExitProcess,NULL
  106.         End Start
  107. End
复制代码
PowerShell
  1. [int] $total=Read-Host -Prompt "请输入人数:";
  2. [int] $remain=Read-Host -Prompt "请输入保留人数:";
  3. [int] $step=Read-Host -Prompt "每隔几个人?:";
  4. $counter=$step;
  5. $arr=[int]1..$total;
  6. $arrcount=$arr.Count;

  7. while($total -gt $remain)
  8. {
  9.         for($i=0;$i -lt $arrcount;$i++) {
  10.         if($arr[$i] -ne 0){$counter--}
  11.         if($counter -eq 0){
  12.             $arr[$i]=[int] 0;
  13.             $counter=$step;
  14.             $total--;
  15.         }
  16.         if($total -le $remain){break}
  17.     }
  18. }

  19. foreach($s in $arr){
  20.     if($s -ne 0){$s}
  21. }
  22. pause;
复制代码
发表于 2019-3-3 16:28:00 | 显示全部楼层
本帖最后由 ivor 于 2019-3-3 22:03 编辑

python
  1. #i:人数  j:步长  alive:存活人数
  2. i = 41; j = 3; alive=2; index = 0; persons = list(range(1, i+1))
  3. while len(persons) > alive:
  4.     index += j - 1
  5.     index %= len(persons)
  6.     print("will to kill %s" % persons.pop(index))
  7.     print("The living people: %s" % persons)
复制代码
结果:
The living people: [16, 31]

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 +1

查看全部评分

发表于 2019-3-3 16:34:03 | 显示全部楼层
nice,坐等吃鸡
发表于 2019-3-3 18:06:03 | 显示全部楼层
本帖最后由 flashercs 于 2019-3-3 18:08 编辑
  1. /**
  2. * delete a member in an array for every nScale numbers loop;
  3. * @param aInput The input array with sequence members
  4. * @param nScale The granularity of the members removation
  5. * @param nRemained The remained members count in the array
  6. */
  7. function removeNO3(aInput = [1, 2, 3, 4, 5, 6], nScale = 3, nRemained = 1) {
  8.   var i = 0;
  9.   aOutput = aInput.slice(0);
  10.   --nScale;
  11.   while (aOutput.length > nRemained) {
  12.     i = (i + nScale) % aOutput.length;
  13.     aOutput.splice(i, 1);
  14.   }
  15.   return aOutput;
  16. }
复制代码
  1. removeNO3([1,2,3,4,5,6,7,8,9,10]);
  2. removeNO3([1,2,3,4,5,6,7,8,9,10],undefined,2);
  3. removeNO3([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],undefined,3);
复制代码

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 +1

查看全部评分

发表于 2019-3-4 01:29:38 | 显示全部楼层
本帖最后由 WHY 于 2019-3-4 16:33 编辑

  1. $i = 41; $j = 3; $k = 2;
  2. $str = 1..$i -join ' ';
  3. $reg = '((?:\d+\s+){' + ($j-1) + '})\d+\s*';

  4. while ( ($str -split '\b[1-9]\d*').Count -1 -$k ) {
  5.     $Len = ($str -split '\d+').Count - 1;
  6.     $str = $str -replace $reg, '$1' -replace '\b0\s';
  7.     $str = '0 ' * ($Len % $j) + $str;
  8. }

  9. $str -replace '\b0\s';
  10. [console]::ReadLine()
复制代码

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 +1

查看全部评分

发表于 2019-3-4 09:46:15 | 显示全部楼层
写一个长的,单向循环链表
  1. STDOUT->autoflush(1);
  2. my $node = {};
  3. my $size = 41;      #元素数量
  4. my $head = $node;
  5. my $ref = $head;
  6. init_node( $node, $size );

  7. while ( $size > 2 ) {
  8.     $iter++;
  9.     if ( $iter % 3 == 0 ) {
  10.         $head = $ref->{next} if ($ref == $head);
  11.         $prev->{next} = $ref->{next};
  12.         $size--;
  13.     }
  14.     $prev = $ref;
  15.     $ref = $ref->{next};
  16. }

  17. print_node($head, $head);

  18. sub print_node {
  19.     my ($ref, $head) = @_;
  20.     do {
  21.         printf "%d ", $ref->{v};
  22.         $ref = $ref->{next};
  23.     } until ( $ref == $head  );
  24.     printf "\n";
  25. }

  26. # 链表初始化
  27. sub init_node {
  28.     my ($ref, $size) = @_;
  29.     $ref->{v} = 1;
  30.     for my $i ( 2 .. $size ) {
  31.         $ref->{next} = { 'v' => $i, 'next' => $head };
  32.         $ref = $ref->{next};
  33.     }
  34. }
复制代码

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 链表好评

查看全部评分

发表于 2019-3-4 11:17:02 | 显示全部楼层
本帖最后由 523066680 于 2019-3-4 14:11 编辑

C艹
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <list>
  4. using namespace std;

  5. int main() {
  6.     list<int> ele;
  7.     for (int n= 1; n <= 41; n++) ele.push_back(n);
  8.     auto it = ele.begin();
  9.     for (int n = 1; ele.size() > 2; n++ ) {
  10.         it = n % 3 == 0 ? ele.erase( it ) : next(it);
  11.         if ( it == ele.end() ) it = ele.begin();
  12.     }
  13.     for (int n : ele ) cout << n << " ";
  14. }
复制代码
发表于 2020-9-26 00:18:24 | 显示全部楼层
MHL版批处理标准教程 作者是不是走了
发表于 2021-1-30 22:59:53 | 显示全部楼层
回复 2# ivor


    所有的代码,只有这个python的看懂了,这是一个悲伤的故事。。。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 02:08 , Processed in 0.025691 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表