Skip to content

Commit fc173fb

Browse files
Solved Josephus algorithm. Documented MyArray.
1 parent 5249e9a commit fc173fb

File tree

3 files changed

+212
-7
lines changed

3 files changed

+212
-7
lines changed

Data-Structures/Arrays/Implementation.ts renamed to Data-Structures/Arrays/MyArray.ts

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
type NumIndexedObject = { [index: number]: any };
22

3-
export class MyArray<T> {
3+
export default class MyArray<T> {
44

55
public length: number;
66
private data: NumIndexedObject;
@@ -10,6 +10,11 @@ export class MyArray<T> {
1010
this.data = Object.create({});
1111
}
1212

13+
/**
14+
* Get element at given index.
15+
* @param index Index of value to return
16+
* @returns Value, or null if non-existant
17+
*/
1318
public get(index: number): T | null {
1419
if(index > 0 && index < this.length) {
1520
return this.data[index];
@@ -18,13 +23,22 @@ export class MyArray<T> {
1823
return null;
1924
}
2025

26+
/**
27+
* Add element to end of array,i.e. at index Array.length.
28+
* @param item Value/object to push
29+
* @returns Length of array after push
30+
*/
2131
public push(item: T): number {
2232
this.data[this.length] = item; // Add item to end of array
2333
++this.length; // Add 1 to array length
2434

2535
return this.length;
2636
}
2737

38+
/**
39+
* Remove the last element of array.
40+
* @returns Value/object at last index, or null if empty array
41+
*/
2842
public pop(): T | null {
2943
if(this.length > 0) {
3044
const lastItem = this.data[this.length-1]; // Retrieve last item
@@ -37,29 +51,40 @@ export class MyArray<T> {
3751
return null;
3852
}
3953

54+
/**
55+
* Delete item at given index.
56+
* @param index Numerical position to delete
57+
* @returns Value/object at index, or null if empty array
58+
*/
4059
public deleteIndex(index: number): T | null {
41-
if(index > 0 && index < this.length) {
60+
if(index >= 0 && index < this.length) {
4261

4362
const requestedItem = this.data[index];
44-
this.shiftItemsLeftAfterIndex(index);
63+
this._shiftItemsLeftAfterIndex(index);
4564

4665
return requestedItem;
4766
}
4867

4968
return null;
5069
}
5170

71+
/**
72+
* Insert a given value (item) at specified index
73+
* @param index Numerical position to insert at
74+
* @param item Value/object to insert
75+
* @returns Length of array after insertion, or null if failed insertion
76+
*/
5277
public insertItemAtIndex(index: number, item: T): number | null {
53-
if(index > 0 && index < this.length) {
54-
this.shiftItemsRightAtIndex(index);
78+
if(index >= 0 && index < this.length) {
79+
this._shiftItemsRightAtIndex(index);
5580
this.data[index] = item;
5681
return this.length;
5782
}
5883

5984
return null;
6085
}
6186

62-
private shiftItemsLeftAfterIndex(index: number): void {
87+
private _shiftItemsLeftAfterIndex(index: number): void {
6388
for (let i=index; i < this.length-1; ++i) {
6489
this.data[i] = this.data[i+1];
6590
}
@@ -68,7 +93,7 @@ export class MyArray<T> {
6893
delete this.data[this.length];
6994
}
7095

71-
private shiftItemsRightAtIndex(index: number): void {
96+
private _shiftItemsRightAtIndex(index: number): void {
7297
++this.length;
7398

7499
for (let i=this.length-1; i > index; --i) {

Playground/Challenges/Josephus.ts

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
export default class Josephus {
2+
private numberOfSoldiers: number;
3+
private circleOfSoldiers: Array<boolean>;
4+
private livingCount: number;
5+
6+
constructor(numSoldiers: number) {
7+
this.numberOfSoldiers = numSoldiers > 1 ? numSoldiers : 2;
8+
this.circleOfSoldiers = new Array(this.numberOfSoldiers).fill(true);
9+
this.livingCount = this.numberOfSoldiers;
10+
}
11+
12+
public setNumSoldiers(numSoldiers: number) {
13+
this.numberOfSoldiers = numSoldiers;
14+
this.reset();
15+
}
16+
17+
public getNumSoldiers(): number {
18+
return this.numberOfSoldiers;
19+
}
20+
21+
public reset(): void {
22+
this.circleOfSoldiers = new Array(this.numberOfSoldiers).fill(true);
23+
this.livingCount = this.numberOfSoldiers;
24+
}
25+
26+
public solveBF(): number {
27+
if (this.numberOfSoldiers < 2) return 0;
28+
29+
let lastKnight: number = -1;
30+
let dead = Array<number>();
31+
32+
for (let i=this._findThirdLiving(0); this.livingCount > 1; i = this._findThirdLiving(i)) {
33+
34+
this._markDead(i)
35+
dead.push(i+1);
36+
i = this._findNextLiving(i);
37+
38+
if (this.livingCount === 1) lastKnight = i;
39+
}
40+
this.reset();
41+
return lastKnight;
42+
}
43+
44+
public solveVisual(): number {
45+
if (this.numberOfSoldiers < 2) return 0;
46+
47+
let lastKnight: number = -1;
48+
49+
console.log('\nThe Romans prepare to clear the caves.\n');
50+
51+
let dead = Array<number>();
52+
53+
for (let i=this._findThirdLiving(0); this.livingCount > 1; i = this._findThirdLiving(i)) {
54+
55+
this._markDead(i)
56+
dead.push(i+1);
57+
console.log('\tKnight', i+1, 'is slain.');
58+
i = this._findNextLiving(i);
59+
console.log('Knight', i+1, 'prepares to strike the next blow.')
60+
61+
if (this.livingCount === 1) {
62+
console.log('But sees no one meet his gaze...');
63+
lastKnight = i;
64+
}
65+
}
66+
67+
console.log('\nK'+(lastKnight+1), 'is the last knight standing.');
68+
69+
console.log('\nSlain knights:', dead.toString());
70+
71+
this.reset();
72+
73+
return lastKnight;
74+
}
75+
76+
private _findNextLiving(index: number): number {
77+
for (let i = (index+1)%this.numberOfSoldiers; this.livingCount>0; i = (i+1)%this.numberOfSoldiers) {
78+
if (this.circleOfSoldiers[i] === true) return i;
79+
}
80+
81+
return -1;
82+
}
83+
84+
private _findThirdLiving(index: number): number {
85+
let counter = 0;
86+
87+
for (let i = (index+1)%this.numberOfSoldiers; this.livingCount>1; i = (i+1)%this.numberOfSoldiers) {
88+
89+
if (this.circleOfSoldiers[i] === true) {
90+
if (counter < 3) ++counter;
91+
}
92+
93+
if (counter === 3) return i;
94+
}
95+
96+
return -1;
97+
}
98+
99+
private _markDead(index:number): number {
100+
this.circleOfSoldiers[index] = false;
101+
--this.livingCount;
102+
return index;
103+
}
104+
}
105+
106+
function printJosephusSolution(circleOfKnights: Josephus) {
107+
console.log('\nSolution for Circle of', circleOfKnights.getNumSoldiers(),'\n– Last Knight at Index:', circleOfKnights.solveBF());
108+
}
109+
110+
//---------------------------------------------------------------------
111+
// ---------- MAIN PROGRAM ----------
112+
//---------------------------------------------------------------------
113+
if (import.meta.main) {
114+
115+
const knights1 = new Josephus(-1);
116+
knights1.solveVisual();
117+
118+
const knights2 = new Josephus(6);
119+
knights2.solveVisual();
120+
121+
const knights3 = new Josephus(8);
122+
knights3.solveVisual();
123+
printJosephusSolution(knights3);
124+
125+
// RUN: deno run Playground/Challenges/Josephus.ts
126+
}
127+
128+
// --------------------------- Terminal Output: ---------------------------
129+
// The Romans prepare to clear the caves.
130+
//
131+
// Knight 2 is slain.
132+
// Knight 1 prepares to strike the next blow.
133+
// But sees no one meet his gaze...
134+
//
135+
// K1 is the last knight standing.
136+
//
137+
// Slain knights: 2
138+
//
139+
// The Romans prepare to clear the caves.
140+
//
141+
// Knight 4 is slain.
142+
// Knight 5 prepares to strike the next blow.
143+
// Knight 2 is slain.
144+
// Knight 3 prepares to strike the next blow.
145+
// Knight 1 is slain.
146+
// Knight 3 prepares to strike the next blow.
147+
// Knight 3 is slain.
148+
// Knight 5 prepares to strike the next blow.
149+
// Knight 6 is slain.
150+
// Knight 5 prepares to strike the next blow.
151+
// But sees no one meet his gaze...
152+
//
153+
// K5 is the last knight standing.
154+
//
155+
// Slain knights: 4,2,1,3,6
156+
//
157+
// The Romans prepare to clear the caves.
158+
//
159+
// Knight 4 is slain.
160+
// Knight 5 prepares to strike the next blow.
161+
// Knight 8 is slain.
162+
// Knight 1 prepares to strike the next blow.
163+
// Knight 5 is slain.
164+
// Knight 6 prepares to strike the next blow.
165+
// Knight 2 is slain.
166+
// Knight 3 prepares to strike the next blow.
167+
// Knight 1 is slain.
168+
// Knight 3 prepares to strike the next blow.
169+
// Knight 3 is slain.
170+
// Knight 6 prepares to strike the next blow.
171+
// Knight 7 is slain.
172+
// Knight 6 prepares to strike the next blow.
173+
// But sees no one meet his gaze...
174+
//
175+
// K6 is the last knight standing.
176+
//
177+
// Slain knights: 4,8,5,2,1,3,7
178+
//
179+
// Solution for Circle of 8
180+
// – Last Knight at Index: 5

0 commit comments

Comments
 (0)