标题: 不限语言解决“约瑟夫问题” [打印本页]
作者: 老刘1号 时间: 2019-3-3 15:58 标题: 不限语言解决“约瑟夫问题”
本帖最后由 老刘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 个位置,于是逃过了这场死亡
游戏。
汇编-一维数组版- ;约瑟夫问题(一维数组) Algo
- ;Code By 老刘
- ;环境:MASM32 SDK
- ;编译指令:ml /coff 约瑟夫问题(一维数组).asm /link /subsystem:console
- ;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。
- ;参数最大值:999999。
- ;参考:MHL批处理标准教程之约瑟夫问题。
-
-
- Include masm32rt.inc
- Main Proto
-
- .Data?
- bBuffer DB 999999 Dup (?)
- dwAll DD ?
- dwPersist DD ?
- bBuffer2 DB 11 Dup (?)
- dwCrLfZero DD ?
- dwJumpPlusOne DD ?
- ;End Data?
-
- .Code
- Main Proc
- ;获得参数
- Invoke ArgClC,1,Offset bBuffer2
- Sub Esp,4
- Invoke atodw_ex,Offset bBuffer2
- Add Esp,4
- Mov dwAll,Eax
- Invoke ArgClC,2,Offset bBuffer2
- Sub Esp,4
- Invoke atodw_ex,Offset bBuffer2
- Add Esp,4
- Mov dwPersist,Eax
- Invoke ArgClC,3,Offset bBuffer2
- Sub Esp,4
- Invoke atodw_ex,Offset bBuffer2
- Add Esp,4
- Mov dwJumpPlusOne,Eax
-
- ;开始标记
- Lea Ebx,bBuffer
- Add Ebx,dwAll
- Mov Edx,dwAll
- Lea Esi,bBuffer
- Mov Edi,Esi
- Xor Eax,Eax
- .While Edx != dwPersist
- Mov Ecx,dwJumpPlusOne
- .Repeat
- LodSB
- Add Ecx,Eax
- .If Esi == Ebx
- Mov Esi,Edi
- .EndIf
- .UntilCxZ
- .If Esi == Edi
- Mov Byte Ptr [Ebx-1],1
- .Else
- Dec Esi
- Mov Byte Ptr [Esi],1
- Inc Esi
- .EndIf
- Dec Edx
- .EndW
-
- ;输出
- Mov dwCrLfZero,000D0AH
- Xor Ecx,Ecx
- Lea Esi,bBuffer
- Dec Esi
- .While Ecx != dwAll
- Inc Ecx
- .If Byte Ptr [Esi+Ecx] == 0
- Pushad
- Invoke dw2a,Ecx,Offset bBuffer2
- Invoke StdOut,Offset bBuffer2
- Invoke StdOut,Offset dwCrLfZero
- Popad
- .EndIf
- .EndW
-
- Ret
- Main EndP
-
- Start:
- Call Main
- Invoke ExitProcess,NULL
- End Start
- End
复制代码
汇编-单向循环链表版- ;约瑟夫问题(单向循环链表) Algo
- ;Code By 老刘
- ;环境:MASM32 SDK
- ;编译指令:ml /coff 约瑟夫问题(单向循环链表).asm /link /subsystem:console
- ;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。
- ;参数最大值:1227。
- ;参考:MHL批处理标准教程之约瑟夫问题。
-
-
- Include masm32rt.inc
- Main Proto
-
- OneWayLinkedList Struct
- Data DWord ?
- Next DWord ?
- OneWayLinkedList EndS
-
- .Data?
- dwAll DD ?
- dwPersist DD ?
- dwJump DD ?
- bBuffer2 DB 11 Dup (?)
- dwCrLfZero DD ?
- dwLinkedListHead DD ?
- ;End Data?
-
- .Code
- Main Proc
- ;获得并处理参数
- Invoke ArgClC,1,Offset bBuffer2
- Sub Esp,4
- Invoke atodw_ex,Offset bBuffer2
- Add Esp,4
- Mov dwAll,Eax
- Invoke ArgClC,2,Offset bBuffer2
- Sub Esp,4
- Invoke atodw_ex,Offset bBuffer2
- Add Esp,4
- Mov dwPersist,Eax
- Invoke ArgClC,3,Offset bBuffer2
- Sub Esp,4
- Invoke atodw_ex,Offset bBuffer2
- Add Esp,4
- Dec Eax
- Mov dwJump,Eax
-
- ;创建链表
- Assume Ebx:Ptr OneWayLinkedList
- Assume Eax:Ptr OneWayLinkedList
- Invoke Alloc,SizeOf OneWayLinkedList
- Mov dwLinkedListHead,Eax
- Mov Ecx,dwAll
- Dec Ecx
- Xor Edx,Edx
- .Repeat
- Mov Ebx,Eax
- Inc Edx
- Push Ecx
- Push Edx
- Invoke Alloc,SizeOf OneWayLinkedList
- Pop Edx
- Pop Ecx
- Mov [Ebx].Next,Eax
- Mov [Ebx].Data,Edx
- .UntilCxZ
- Mov Ebx,Eax
- Inc Edx
- Push dwLinkedListHead
- Pop [Ebx].Next ;指向链表结点1
- Mov [Ebx].Data,Edx
- ;此时Ebx指向尾结点
-
- ;开始标记
- Mov Edx,dwAll
- .While Edx != dwPersist
- Mov Ecx,dwJump
- .If Ecx != 0
- .Repeat
- Mov Ebx,[Ebx].Next
- .UntilCxZ
- .EndIf
- Mov Eax,[Ebx].Next
- Mov Ecx,[Eax].Next
- Mov [Ebx].Next,Ecx
- Push Edx
- Invoke Free,Eax
- Pop Edx
- Dec Edx
- .EndW
-
- ;遍历链表并输出
- Mov dwCrLfZero,000D0AH
- Mov Ecx,Ebx
- .Repeat
- Pushad
- Invoke dw2a,[Ebx].Data,Offset bBuffer2
- Invoke StdOut,Offset bBuffer2
- Invoke StdOut,Offset dwCrLfZero
- Popad
- Mov Ebx,[Ebx].Next
- .Until Ebx == Ecx
- Assume Ebx:Nothing
- Assume Eax:Nothing
-
- Ret
- Main EndP
-
- Start:
- Call Main
- Invoke ExitProcess,NULL
- End Start
- End
复制代码
PowerShell- [int] $total=Read-Host -Prompt "请输入人数:";
- [int] $remain=Read-Host -Prompt "请输入保留人数:";
- [int] $step=Read-Host -Prompt "每隔几个人?:";
- $counter=$step;
- $arr=[int]1..$total;
- $arrcount=$arr.Count;
-
- while($total -gt $remain)
- {
- for($i=0;$i -lt $arrcount;$i++) {
- if($arr[$i] -ne 0){$counter--}
- if($counter -eq 0){
- $arr[$i]=[int] 0;
- $counter=$step;
- $total--;
- }
- if($total -le $remain){break}
- }
- }
-
- foreach($s in $arr){
- if($s -ne 0){$s}
- }
- pause;
复制代码
作者: ivor 时间: 2019-3-3 16:28
本帖最后由 ivor 于 2019-3-3 22:03 编辑
python- #i:人数 j:步长 alive:存活人数
- i = 41; j = 3; alive=2; index = 0; persons = list(range(1, i+1))
- while len(persons) > alive:
- index += j - 1
- index %= len(persons)
- print("will to kill %s" % persons.pop(index))
- print("The living people: %s" % persons)
复制代码
结果:
The living people: [16, 31]
作者: 曾经的你 时间: 2019-3-3 16:34
nice,坐等吃鸡
作者: flashercs 时间: 2019-3-3 18:06
本帖最后由 flashercs 于 2019-3-3 18:08 编辑
- /**
- * delete a member in an array for every nScale numbers loop;
- * @param aInput The input array with sequence members
- * @param nScale The granularity of the members removation
- * @param nRemained The remained members count in the array
- */
- function removeNO3(aInput = [1, 2, 3, 4, 5, 6], nScale = 3, nRemained = 1) {
- var i = 0;
- aOutput = aInput.slice(0);
- --nScale;
- while (aOutput.length > nRemained) {
- i = (i + nScale) % aOutput.length;
- aOutput.splice(i, 1);
- }
- return aOutput;
- }
复制代码
- removeNO3([1,2,3,4,5,6,7,8,9,10]);
- removeNO3([1,2,3,4,5,6,7,8,9,10],undefined,2);
- removeNO3([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],undefined,3);
复制代码
作者: WHY 时间: 2019-3-4 01:29
本帖最后由 WHY 于 2019-3-4 16:33 编辑
- $i = 41; $j = 3; $k = 2;
- $str = 1..$i -join ' ';
- $reg = '((?:\d+\s+){' + ($j-1) + '})\d+\s*';
-
- while ( ($str -split '\b[1-9]\d*').Count -1 -$k ) {
- $Len = ($str -split '\d+').Count - 1;
- $str = $str -replace $reg, '$1' -replace '\b0\s';
- $str = '0 ' * ($Len % $j) + $str;
- }
-
- $str -replace '\b0\s';
- [console]::ReadLine()
复制代码
作者: 523066680 时间: 2019-3-4 09:46
写一个长的,单向循环链表- STDOUT->autoflush(1);
- my $node = {};
- my $size = 41; #元素数量
- my $head = $node;
- my $ref = $head;
- init_node( $node, $size );
-
- while ( $size > 2 ) {
- $iter++;
- if ( $iter % 3 == 0 ) {
- $head = $ref->{next} if ($ref == $head);
- $prev->{next} = $ref->{next};
- $size--;
- }
- $prev = $ref;
- $ref = $ref->{next};
- }
-
- print_node($head, $head);
-
- sub print_node {
- my ($ref, $head) = @_;
- do {
- printf "%d ", $ref->{v};
- $ref = $ref->{next};
- } until ( $ref == $head );
- printf "\n";
- }
-
- # 链表初始化
- sub init_node {
- my ($ref, $size) = @_;
- $ref->{v} = 1;
- for my $i ( 2 .. $size ) {
- $ref->{next} = { 'v' => $i, 'next' => $head };
- $ref = $ref->{next};
- }
- }
复制代码
作者: 523066680 时间: 2019-3-4 11:17
本帖最后由 523066680 于 2019-3-4 14:11 编辑
C艹- #include <algorithm>
- #include <iostream>
- #include <list>
- using namespace std;
-
- int main() {
- list<int> ele;
- for (int n= 1; n <= 41; n++) ele.push_back(n);
- auto it = ele.begin();
- for (int n = 1; ele.size() > 2; n++ ) {
- it = n % 3 == 0 ? ele.erase( it ) : next(it);
- if ( it == ele.end() ) it = ele.begin();
- }
- for (int n : ele ) cout << n << " ";
- }
复制代码
作者: txiceg 时间: 2020-9-26 00:18
MHL版批处理标准教程 作者是不是走了
作者: 459500160 时间: 2021-1-30 22:59
回复 2# ivor
所有的代码,只有这个python的看懂了,这是一个悲伤的故事。。。。。
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |