Introduction
- It is quite common for systems to use 6-digit secret codes to authenticate users.
- Delivery usually via email or SMS
- For example: 435 657
Algorithm
- In this algorithm, using parallelism, the algorithm uses the 8 available CPUs in parallel here on my machine.
- I made a logic so that each worker processes an amount of equal numbers.
- Example: if I have 32 possible numbers to check, each worker will check 4 different numbers, in parallel, at the same time.
- When one of the workers finds the secret code, it sends a message to the master cluster of the 8 workers to finish the work of all of them.
Conclusion
- I made this algorithm for didactic purposes, and for pure curiosity/technical interest.
Script Example in Javascript
const cluster = require("cluster");
const totalCPUs = require("os").cpus().length;
const secretCodeToFind = 213405;
const minNumber = 100000;
const maxNumber = 999999;
const totalNumbersToEachWorkerToTest = Math.floor(
(maxNumber - minNumber) / totalCPUs
);
const indexes = [0, 1, 2, 3, 4, 5, 6, 7];
const startAt = []; // numbers to each worker start to test
const endAt = []; // numbers to each worker end test
for (let i = 0; i < indexes.length; i++) {
if (i === 0) {
startAt[0] = minNumber;
endAt[0] = minNumber + totalNumbersToEachWorkerToTest;
} else {
startAt[i] = endAt[i - 1] + 1;
endAt[i] =
startAt[i] + totalNumbersToEachWorkerToTest > maxNumber
? maxNumber
: startAt[i] + totalNumbersToEachWorkerToTest;
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
if (cluster.isMaster) {
for (let i = 0; i < totalCPUs; i++) {
const worker = cluster.fork();
worker.on("message", message => {
console.log(
`\nWORKER ID ${worker.process.pid} => received message: ${message}\n`
);
if (message === "SECRET CODE FOUND") {
console.log(
`\nThe Secret Code ${secretCodeToFind} was found! Terminating all workers...\n`
);
for (const id in cluster.workers) {
cluster.workers[id].kill();
}
}
});
}
let workerIndex = 0;
for (const index of indexes) {
const worker = Object.values(cluster.workers)[workerIndex];
if (worker) {
const object = {
start: startAt[index],
end: endAt[index],
};
worker.send(object);
workerIndex = (workerIndex + 1) % totalCPUs;
}
}
cluster.on("exit", (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} finished his job!`);
});
} else {
process.on("message", async ({ start, end }) => {
for (let i = start; i <= end; i++) {
console.log(`...WORKER ID ${process.pid} => trying number: ${i}`);
await sleep(25);
if (i === secretCodeToFind) {
console.log(`\n\nTHE SECRET CODE is =========> ${i}\n\n`);
process.send("SECRET CODE FOUND");
break;
}
}
});
}
Script Example in Go
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
const (
secretCodeToFind = 213405
minNumber = 100000
maxNumber = 999999
)
var (
totalNumbersToEachWorkerToTest int
startAt []int
endAt []int
)
func initRanges(numWorkers int) {
startAt = make([]int, numWorkers)
endAt = make([]int, numWorkers)
for i := 0; i < numWorkers; i++ {
if i == 0 {
startAt[0] = minNumber
endAt[0] = minNumber + totalNumbersToEachWorkerToTest
} else {
startAt[i] = endAt[i-1] + 1
endAt[i] = startAt[i] + totalNumbersToEachWorkerToTest
if endAt[i] > maxNumber {
endAt[i] = maxNumber
}
}
}
}
func sleep(ms int) {
time.Sleep(time.Duration(ms) * time.Millisecond)
}
func Worker(id, start, end int, wg *sync.WaitGroup, found chan struct{}) {
defer wg.Done()
for i := start; i <= end; i++ {
select {
case <-found:
return
default:
fmt.Printf("...WORKER ID %d => trying number: %d\n", id, i)
sleep(25)
if i == secretCodeToFind {
fmt.Printf("\n\nTHE SECRET CODE is =========> %d\n\n", i)
close(found)
return
}
}
}
}
func main() {
numWorkers := runtime.NumCPU()
totalNumbersToEachWorkerToTest = (maxNumber - minNumber) / numWorkers
initRanges(numWorkers)
var wg sync.WaitGroup
found := make(chan struct{})
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go Worker(i, startAt[i], endAt[i], &wg, found)
}
wg.Wait()
}