নতুন অ্যালগরিদম, এটি যদি এইবার আসলে কাজ করে তা ব্যাখ্যা করবে।
const {performance} = require('perf_hooks');
class Connection{
constructor(left,index,length,right){
if(typeof right === 'undefined'){
this._distance = 0;
} else {
this._distance = typeof left === 'undefined' ? 0 :
Math.abs(right - left);
}
var half = Math.floor(length/2);
if(length % 2 < 1){
this._magnitude = half - Math.abs(index - half + 1);
} else {
var temp = index - half;
this._magnitude = half - Math.abs(temp >= 0 ?temp:temp + 1);
}
this._value = this.distance * this.magnitude;
}
get distance(){return this._distance;};
get magnitude(){return this._magnitude;};
set magnitude(value){
this._magnitude = value;
this._value = this.distance * this.magnitude;
};
valueOf(){return this._value};
}
class Group{
constructor(...connections){
this._connections = connections;
this._max = Math.max(...connections); //uses the ValueOf to get the highest Distance to the Left
}
get connections(){return this._connections;};
get max(){return this._max;};
cutLeft(index){
for(let i=1,j=index-1;;i++){
if(typeof this.connections[j] === 'undefined' || this.connections[j].magnitude <= i){
break;
}
this.connections[j].magnitude = i;
j--;
}
}
cutRight(index){
for(let i=0,j=index;;i++){
if(typeof this.connections[j] === 'undefined' || this.connections[j].magnitude <= i){
break;
}
this.connections[j].magnitude = i;
j++;
}
}
static of(...connections){
return new Group(...connections.map((c,i)=>new Connection(c.distance,i,connections.length)));
}
split(){
var index = this.connections.findIndex(c=>c.valueOf() == this.max);
if(index < 0){
return;
}
var length = this.connections.length;
var magnitude = this.connections[index].magnitude;
this.cutLeft(index);
this.cutRight(index);
this._max = Math.max(...this.connections);
}
center(){
if(typeof this._center === 'undefined'){
this._center = this.connections.reduce((a,b)=>a==0?b.valueOf():a.valueOf()+b.valueOf(),0);
}
return this._center;
}
valueOf(){return this._max;};
toString(){
var index = this.connections.findIndex(c=>c.valueOf() == this.max);
var value = this.connections[index].magnitude;
var ret = '';
for(let i = 0;i<value;i++){
ret += this.connections.map(c=>{return (i<c.magnitude)?c.distance:' ';}).reduce((a,b)=>a==''?b:a+'-'+b,'') + '\n';
}
return ret;
};
}
function crunch(plants, cities){
var found = [];
var size = cities.length;
cities = cities.map((city,i,arr)=> new Connection(city,i,size,arr[i+1])).slice(0,cities.length-1);
var group = new Group(...cities);
for(;plants>1;plants--){
group.split();
}
console.log(`Wire Length Needed: ${group.center()}`);
}
function biggestGroup(groups){
return groups.find(g => g[g.length-1].orig - g[0].orig);
}
function* range (start, end, limit) {
while (start < end || typeof limit !== 'undefined' && limit-- > 0) {
yield start
start += 1 + Math.floor(Math.random()*100);
}
}
function* cities (score){
let n = Math.floor(Math.pow(2,score/5));
var start = 0;
while (n-- > 0 && start <= (1000 * n)) {
yield start;
start += 1 + Math.floor(Math.random()*100);
}
}
if(typeof process.argv[3] === 'undefined'){
crunch(1,[0, 2, 4, 6, 8]);
console.log("Correct Answer: 12");
crunch(3,[0, 1, 10, 11, 20, 21, 22, 30, 32]);
console.log("Correct Answer: 23");
crunch(5,[0, 1, 3, 6, 8, 11, 14]);
console.log("Correct Answer: 3");
crunch(6,[0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84]);
console.log("Correct Answer: 49");
crunch(2, [0, 21, 31, 45, 49, 54]);
console.log("Correct Answer: 40");
crunch(2, [0, 4, 7, 9, 10]);
console.log("Correct Answer: 7");
crunch(2, [0, 1, 3, 4, 9]);
console.log("Correct Answer: 6");
var max = 0;
var min = Number.POSITIVE_INFINITY;
var avg = [];
var score = typeof process.argv[2] === 'undefined' ? 60 : process.argv[2];
for(j = 0; j<10; j++){
var arr = []; for(let i of cities(score)) arr.push(i);
var plants = Math.floor(1 + Math.random() * arr.length);
console.log(`Running: Test:${j} Plants: ${plants}, Cities ${arr.length}, Score: ${score}`);
// console.log(`City Array: [${arr}]`);
var t0 = performance.now();
crunch(plants,arr);
var t1 = performance.now();
time = (t1-t0)/1000;
console.log(`Time Taken = ${time} seconds`);
avg.push(time);
max = Math.max(time,max);
min = Math.min(time,min);
}
console.log(`Bench: ${avg.reduce((a,b)=>a+b,0)/avg.length} Max: ${max} Min: ${min} Total: ${avg.reduce((a,b)=>a+b,0)}`);
} else {
var plants = process.argv[2];
var arr = process.argv.slice(3);
console.log(`Running: Plants: ${plants}, Cities ${arr.length}`);
var t0 = performance.now();
crunch(plants,arr);
var t1 = performance.now();
time = (t1-t0)/1000;
console.log(`Time Taken = ${time} seconds`);
}
এটি অনলাইন চেষ্টা করুন!
অন্যটির মতো একইভাবে চালান।
অ্যালগরিদমের রূপরেখা:
প্রোগ্রামটি প্রথমে সিটি ক্লাসে ডেটা ম্যাপ করে, যা কয়েকটি ডেটা পয়েন্ট ম্যাপ করে:
- শহর - শহরের পরম দূরত্ব
- বাম - বাম নিকটতম শহরের দূরত্ব
- ডান - নিকটতম শহর থেকে ডানদিকে দূরত্ব
- সূচক - (মূলত শহর অ্যারেতে সূচিত) সূচক
অ্যারেটি তখন গ্রুপ ক্লাসে নিক্ষেপ করা হয়, যার নিম্নলিখিতটি রয়েছে:
- শহর - শহর অ্যারে
- দূর - গ্রুপ বিস্তৃত দূরত্ব
- সর্বাধিক - গ্রুপের বৃহত্তম বাম সংযোগ
- বিভক্ত ()
- গ্রুপের কেন্দ্রের শহরের সাথে সংযোগযুক্ত বৃহত্তম সংযোগের সাথে উপগোষ্ঠী বিভক্ত একটি অ্যারে প্রদান করে
- যদি 2 টি কেন্দ্র নোড থাকে (একটি দৈর্ঘ্যের গ্রুপ) তবে এটি 3 টি সংযোগ থেকে চয়ন করে choo
- (* দ্রষ্টব্য *: এটি দুটি শহরেরও কম সংখ্যক গ্রুপকেই ফেলে দেবে)
- কেন্দ্র ()
- গোষ্ঠীর জন্য সেরা তারের মান প্রদান করে
- এই পদক্ষেপের জন্য ছেড়ে যাওয়া প্রতিটি শহরে পুনরাবৃত্তি ছেড়ে যাওয়ার সমাধানে কাজ করা
- এখন 50% কম ম্যাপিং সহ
এখন অ্যালগরিদম যতক্ষণ না 2 বা ততোধিক পাওয়ার প্ল্যান্ট রাখে ততক্ষণ গ্রুপগুলিকে বিভক্ত করতে এগিয়ে যায়।
শেষ পর্যন্ত এটি দলগুলিকে এর কেন্দ্রগুলিতে ম্যাপ করে এবং এগুলি সমস্ত সংখ্যার যোগফল দেয়।
কীভাবে চালাবেন:
নোড.জেএস ব্যবহার করে চালান (v9.2.0 যা সৃষ্টির জন্য ব্যবহৃত হয়েছিল)
স্কোর 70 এর জন্য উত্পন্ন পরীক্ষার কেসগুলি ব্যবহার করে প্রোগ্রামটি চালাচ্ছেন:
node program.js 70
1 টি বিদ্যুৎ কেন্দ্র এবং শহরগুলি [0,3,5] ব্যবহার করে প্রোগ্রামটি চালাচ্ছে:
node program.js 1 0 3 5
কোড:
const {performance} = require('perf_hooks');
class City{
constructor(city, left, right, i){
this._city = city;
this._index = i;
this._left = typeof left === 'undefined' ? 0 : city - left;
this._right = typeof right === 'undefined' ? 0 : right - city;
}
get city(){return this._city;};
get index(){return this._index;};
get left(){return this._left;};
get right(){return this._right;};
set left(left){this._left = left};
set right(right){this._right = right};
valueOf(){return this._left;};
}
class Group{
constructor(...cities){
this._cities = cities;
// console.log(cities.map(a=>a.city).reduce((a,b)=>a===''?a+(b<10?' '+b:b):a+'-'+(b<10?' '+b:b),""));
// console.log(cities.map(a=>a.left).reduce((a,b)=>a===''?a+(b<10?' '+b:b):a+'-'+(b<10?' '+b:b),""));
// console.log(cities.map(a=>a.right).reduce((a,b)=>a===''?a+(b<10?' '+b:b):a+'-'+(b<10?' '+b:b),""));
// console.log("+==+==+==+==+==+==+==+==+==+==+==+==")
this._dist = cities[cities.length-1].city - cities[0].city;
this._max = Math.max(...cities); //uses the ValueOf to get the highest Distance to the Left
}
get dist(){return this._dist;};
get cities(){return this._cities;};
get max(){return this._max;};
split(){
//var index = this.cities.findIndex(city=>city.left == this.max);
//this.cities[index].left = 0;
// console.log(`Slicing-${this.max}-${index}------`)
var centerIndex = this.cities.length / 2;
var splitIndex = Math.floor(centerIndex);
if(centerIndex%1 > 0){
var center = this.cities[splitIndex];
if(center.right > center.left){
splitIndex++;
}
} else {
var right = this.cities[splitIndex];
var left = this.cities[splitIndex-1];
if(left.left > Math.max(right.right,right.left)){
splitIndex--;
} else if(right.right > Math.max(left.left,left.right)){
splitIndex++;
}
}
// console.log(splitIndex);
this.cities[splitIndex].left = 0;
this.cities[splitIndex-1].right = 0;
var leftCities = [...this.cities.slice(0,splitIndex)];
var rightCities = [...this.cities.slice(splitIndex)];
// var center = this.cities[]
if(leftCities.length <= 1){
if(rightCities.length <= 1){
return [];
}
return [new Group(...rightCities)]
}
if(rightCities.length <= 1){
return [new Group(...leftCities)];
}
return [new Group(...leftCities), new Group(...rightCities)];
}
center(){
if(typeof this._center === 'undefined'){
if(this.cities.length == 1){
return [0];
}
if(this.cities.length == 2){
return this.cities[1].left;
}
var index = Math.floor(this.cities.length/2);
this._center = this.cities.reduce((a,b)=> {
// console.log(`${a} + (${b.city} - ${city.city})`);
return a + Math.abs(b.city - this.cities[index].city);
},0);
// console.log(this._center);
}
return this._center;
}
valueOf(){return this._max;};
}
function crunch(plants, cities){
var found = [];
var size = cities.length;
cities = cities.map((city,i,arr)=> new City(city,arr[i-1],arr[i+1],i));
var groups = [new Group(...cities)];
// console.log(groups);
for(;plants>1;plants--){
var mapped = groups.map(g=>g.center()-g.max);
var largest = Math.max(...groups);
// console.log('Largest:',largest)
// console.log(...mapped);
var index = groups.findIndex((g,i)=> mapped[i] == g.center() - g.max && g.max == largest);
// console.log(index);
groups = index == 0 ?
[...groups[index].split(),...groups.slice(index+1)]:
[...groups.slice(0,index),...groups[index].split(),...groups.slice(index+1)];
}
// console.log(`=Cities=${size}================`);
// console.log(groups);
size = groups.map(g=>g.cities.length).reduce((a,b)=>a+b,0);
// console.log(`=Cities=${size}================`);
var wires = groups.map(g=>g.center());
// console.log(...wires);
// console.log(`=Cities=${size}================`);
console.log(`Wire Length Needed: ${wires.reduce((a,b)=>a + b,0)}`);
}
function biggestGroup(groups){
return groups.find(g => g[g.length-1].orig - g[0].orig);
}
function* range (start, end, limit) {
while (start < end || typeof limit !== 'undefined' && limit-- > 0) {
yield start
start += 1 + Math.floor(Math.random()*100);
}
}
function* cities (score){
let n = Math.floor(Math.pow(2,score/5));
var start = 0;
while (n-- > 0 && start <= (1000 * n)) {
yield start;
start += 1 + Math.floor(Math.random()*100);
}
}
if(typeof process.argv[3] === 'undefined'){
crunch(1,[0, 2, 4, 6, 8]);
console.log("Correct Answer: 12");
crunch(3,[0, 1, 10, 11, 20, 21, 22, 30, 32]);
console.log("Correct Answer: 23");
crunch(5,[0, 1, 3, 6, 8, 11, 14]);
console.log("Correct Answer: 3");
crunch(6,[0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84]);
console.log("Correct Answer: 49");
crunch(2, [0, 21, 31, 45, 49, 54]);
console.log("Correct Answer: 40");
crunch(2, [0, 4, 7, 9, 10]);
console.log("Correct Answer: 7");
var max = 0;
var min = Number.POSITIVE_INFINITY;
var avg = [];
var score = typeof process.argv[2] === 'undefined' ? 60 : process.argv[2];
for(j = 0; j<10; j++){
var arr = []; for(let i of cities(score)) arr.push(i);
var plants = Math.floor(1 + Math.random() * arr.length);
console.log(`Running: Test:${j} Plants: ${plants}, Cities ${arr.length}, Score: ${score}`);
var t0 = performance.now();
crunch(plants,arr);
var t1 = performance.now();
time = (t1-t0)/1000;
console.log(`Time Taken = ${time} seconds`);
avg.push(time);
max = Math.max(time,max);
min = Math.min(time,min);
}
console.log(`Bench: ${avg.reduce((a,b)=>a+b,0)/avg.length} Max: ${max} Min: ${min} Total: ${avg.reduce((a,b)=>a+b,0)}`);
} else {
var plants = process.argv[2];
var arr = process.argv.slice(3);
console.log(`Running: Plants: ${plants}, Cities ${arr.length}`);
var t0 = performance.now();
crunch(plants,arr);
var t1 = performance.now();
time = (t1-t0)/1000;
console.log(`Time Taken = ${time} seconds`);
}
এটি অনলাইন চেষ্টা করুন!
আমি মন্তব্য করা কোডটি পরবর্তী কয়েক দিনের মধ্যে পরিষ্কার করব যেহেতু আমি এখনও এটি নিয়ে কাজ করছি, কেবল এটি দেখতে চেয়েছিলাম যে এটি কেবল ছোট ছোট মামলার চেয়ে বেশি পার করছে কিনা।
2^^(x/5)
: অর্থ কি ? আপনি কি কেবল এন এর জন্য একটি উপরের বাউন্ড সরবরাহ করতে পারেন?