是否存在一种算法,可以将数字分解为一个由单个数字组成的 随机集 ,如果将这些数字相乘,最终得到的数字就是给定的相同数字?>
generatePossibility(number, size = 8)
请注意,我每次输入相同的数字时,都不应退还相同的数字。
例如:如果我输入了数字940800
,它将生成以下内容(大小11):
[5, 8, 7, 7, 1, 1, 1, 2, 5, 8, 6]
[3, 4, 1, 2, 4, 5, 5, 8, 7, 7, 1]
[8, 3, 8, 5, 2, 7, 5, 2, 7, 1, 1]
*数字不必唯一。
更新
我意识到在这种情况下并非所有数字都可以。但是,就我而言,由于我是设置数字的人(不是任何用户免费输入的东西),所以我想知道一种算法,可以将一个数字分解为一定大小的一位数字数组。 / p>
我当前的算法效率很低而且不够漂亮:
例如:数字为940,800
function isPrime(num) {
for(var i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 7; // Return any prime number that is not single digit
}
function shuffle(array) {
// Shuffle the array
return array.sort(() => Math.random() - 0.5);
}
function randomInt() {
// returns 1 - 9
return Math.floor((Math.random() * 9) + 1);
}
function removeElement(array, elem) {
const index = array.indexOf(elem);
if (index > -1) {
array.splice(index, 1);
}
}
const shrink = (array, number) => {
removeElement(array, number);
removeElement(array, number);
array.push(number * number);
return array;
}
const expand = (array, number) => {
array.push(number);
array.push(number);
removeElement(array, number * number);
return array;
}
const getRandomDigits = (number, size) => {
let remaining = number;
const list = [];
while (remaining !== 1) {
if (isPrime(remaining)) {
return `Unable to proceed, stuck at prime number ${remaining}`;
}
const randomNumber = randomInt();
if (Number.isInteger(remaining / randomNumber)) {
// Possible number, save it into the list
list.push(randomNumber);
// Update the remaining
remaining /= randomNumber;
}
}
return list;
}
const adjustSize = (array, size) => {
// sort the array in ascending order
let remaining = array.sort((a, b) => a - b);
// if size is lower than desired size
// find count of 4, if there is one, split them into double 2
while (remaining.length < size && remaining.find(e => e === 4)) {
remaining = expand(remaining, 2);
}
// find count of 9, if there is one, split them into double 3
while (remaining.length < size && remaining.find(e => e === 9)) {
remaining = expand(remaining, 3);
}
// add rest of the space with 1
while (remaining.length < size) {
remaining = remaining.push(1);
}
// If remaining has number "1", we can simply remove them
while (remaining.length > size && remaining.includes(1)) {
remaining.shift();
}
// combine possible integers
// find count of 2, if there are two, combine them into single 4
while (remaining.length > size && remaining.filter(e => e === 2).length > 1) {
remaining = shrink(remaining, 2);
}
// find count of 3, if there are two, combine them into single 9
while (remaining.length > size && remaining.filter(e => e === 3).length > 1) {
remaining = shrink(remaining, 3);
}
// the given number is impossible
while (remaining.length > size) {
return `Couldn't generate, please try again! Size: ${remaining.length}`;
}
// possible
return remaining;
}
let endResult = null;
let failedAttempt = 0;
while (!endResult && failedAttempt < 100) {
const randomDigits = getRandomDigits(940800, 12);
if (typeof randomDigits === 'string') {
console.error(randomDigits);
failedAttempt += 1;
continue;
}
const attempt = adjustSize(randomDigits, 12);
if (typeof attempt === 'string') {
console.error(attempt);
failedAttempt += 1;
continue;
}
// Found it
if (Array.isArray(attempt)) {
endResult = shuffle(attempt);
}
}
console.log('Failed attempt', failedAttempt);
console.log('Succeeded Result', endResult);
这有点用,但是很丑。
答案 0 :(得分:2)
首先算出数字的素数。例如,940800是:
2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 3 * 5 * 5 * 7 * 7
然后,要生成这些随机数组之一,请将上面设置的任意数字(或无)随机相乘在一起,直到获得数组中所需项的数量(此处为8)。例如,您可以使用Math.random()
随机选择两个索引(不替换)。例如,假设选择的索引是0和1-那么您将拥有
4 * 2 * 2 * 2 * 2 * 2 * 2 * 3 * 5 * 5 * 7 * 7
也许下一个随机指数是5和8-然后,您将5和8指数相乘:
4 * 2 * 2 * 2 * 2 * 10 * 2 * 3 * 5 * 7 * 7
重复此操作,直到获得所需数量的项目为止。如果需要,您还可以在返回数组之前先对数组进行洗牌。
要将输出数组限制为个位数,请在上述过程中,仅在结果小于10时乘以-否则,请重新选择索引。 (对于某些输入,将无法解决,例如generatePossibility(1000, 1)
。)
答案 1 :(得分:2)
天真的实现部分基于@CertainPerformance建议
function findPrimeFactors(num) {
var primeFactors = [];
while (num % 2 === 0) primeFactors.push(2), num = num / 2;
for (var i = 3; i <= Math.sqrt(num); i++)
while (num % i === 0) primeFactors.push(i), num = num / i;
if (num > 2) primeFactors.push(num);
return primeFactors;
}
function generatePossibility(number, size) {
var factors = findPrimeFactors(number).sort().reverse();
var ret = new Array(size).fill(1);
for (i = 0; i < factors.length; i++) {
var indexes = new Array();
ret.filter((a, idx) => {
if (a * factors[i] < 10)
indexes.push(idx);
});
var randIdx = Math.floor(Math.random() * (indexes.length > 0 ? indexes.length : size));
if (indexes.length > 0)
ret[indexes[randIdx]] *= factors[i];
else
ret[randIdx] *= factors[i];
}
return ret;
}
var possibilities = generatePossibility(940800, 8);
console.log(possibilities.join(","));
console.log(possibilities.reduce((a, b) => a * b));
获取数字的阈值(因子的单个数字组合的最小数组大小):
function findPrimeFactors(num) {
var primeFactors = [];
while (num % 2 === 0) primeFactors.push(2), num = num / 2;
for (var i = 3; i <= Math.sqrt(num); i++)
while (num % i === 0) primeFactors.push(i), num = num / i;
if (num > 2) primeFactors.push(num);
return primeFactors;
}
function getThreshold(num) {
var factors = findPrimeFactors(num).sort().reverse();
if (factors.filter(a => a > 10).length > 0) return -1;
var ret = [factors[0]];
factors = factors.slice(1);
while (factors.length > 0) {
if (ret[ret.length - 1] * factors[0] > 10)
ret.push(factors[0]);
else
ret[ret.length - 1] *= factors[0];
factors = factors.slice(1);
}
return ret.length;
}
console.log(getThreshold(940800));
答案 2 :(得分:0)
这不可能。至少不是只有一位数字数字。
为什么?
因为,假设数字的一个因素是13、17、19、11 ...等,换句话说,一个因素是两位数或三位数的质数怎么办?
答案 3 :(得分:-1)
由于并非每个自然数都使之成为可能,因此将数字绘制为一组数字1、2、3、5、7的复数会更有效(甚至不需要知道乘积)。
现在,如“某些性能”所建议的那样,您可以合并一些数字以将长度减少到所需的值,并避免因素总是相同的。
例如
多重图
1 1 1 1 2 2 2 3 3 3 3 5 7 7
减少到长度8
1 1 1 1 2 2 2 3 3 9 5 7 7
1 1 1 2 2 3 3 9 5 7 7
1 1 2 2 3 3 9 5 7 7
1 1 2 6 3 9 5 7 7
1 1 6 6 9 5 7 7
现在您可以随机播放了。
对于另一个图形,请从最初的多重性重新开始,形成新的合并和新的改组。
请注意,某些情况下会死胡同(无法达到所需的长度)。可达到的最大长度是初始多重性的总和。最小值就像M2/3 + (M2 mod 3)/2 + M3/2 + M5 + M7
之和,如果1
和M2 mod 3=1
是奇数(如果我是对的话),则减去M3
。
(对不起,Python)
l= 9 # Sequence length
n= 5 # Maximal multiplicities
# Generate the prime digits with multiplicities (0 to n-1)
while True:
p= [1] * random.randrange(n) + [2] * random.randrange(n)\
+ [3] * random.randrange(n) + [5] * random.randrange(n)\
+ [7] * random.randrange(n)
if len(p) >= l:
break
# Try to generate ten sequences
for s in range(10):
# Keep a copy
q= copy.deepcopy(p)
# Merge digits to the desired length (aborts after 50 attempts)
count= 50
while len(q) > l and count > 0:
i= random.randrange(len(q))
j= random.randrange(len(q))
if i != j and q[i] * q[j] < 10:
# Merge
q[i]*= q[j]
del q[j]
count-= 1
if count > 0:
random.shuffle(q)
print(q, functools.reduce(operator.mul, q, 1))
[7, 3, 1, 5, 3, 2, 7, 7, 5] 154350
[7, 3, 7, 7, 3, 5, 5, 2, 1] 154350
[2, 3, 1, 3, 5, 7, 7, 7, 5] 154350
[5, 3, 7, 2, 5, 1, 3, 7, 7] 154350
[3, 7, 3, 7, 5, 5, 2, 7, 1] 154350
[2, 7, 3, 7, 7, 1, 3, 5, 5] 154350
[7, 7, 3, 3, 5, 7, 2, 5, 1] 154350
[5, 2, 3, 7, 7, 5, 7, 3, 1] 154350
[7, 7, 2, 1, 5, 3, 7, 5, 3] 154350
[7, 1, 7, 5, 5, 2, 3, 7, 3] 154350