设X是一个已知值,它表示一行将显示多少列(可能的列为1、2、3或4)。
设Y是元素的个数(从1到无穷大)
使用Javascript,是否有任何方法/算法来计算Y中每个元素的宽度,使我们满足X(无论我们使用多少行),并且每个元素的最大大小是2列?
示例1:设X为4(宽屏)和Y为5元素,第一行将包含3个元素,其中一个元素包含2列,第二行包含2个元素,两个元素都包含2列。

示例2:设X为4(宽屏)和Y为7元素,第一行将包含4个元素,使得每个元素都包含1列,第二行包含3个元素,其中一个元素包含2列。(命令无关紧要)

发布于 2020-02-03 21:41:01
由于可能性的数量是相当有限的,您可以只识别这些。很明显,您必须生成多少行并不重要,只有最后两行或最后两行才需要有两个大小的框才能使其适合。所有其他行只能有1列大小的框。
下面是一个函数,它将列出最后几个单元格的宽度,从具有双宽度的第一个单元格开始:
function tail(x, y) {
let mod = y % x;
if (mod == 0) return []; // All items have size 1
if (x == 2 || y == 1) return [2]; // Only last item has size 2
if (x == 3) return [[2, 1, 2, 1], [2, 1]][mod-1];
if (x == 4) return [[2, 1, 1, 2, 2], [2, 2], [2, 1, 1]][mod-1];
}现在我们已经做了艰苦的工作。其余的都变得简单了。我们可以创建另一个函数,它将返回长度为y的每一项的完整宽度数组。
function widths(x, y) {
// Get the special rows that have to appear at the very end
let arrTail = tail(x, y);
// Prepend the number of normal cells (all having size 1):
return Array(y - arrTail.length).fill(1).concat(arrTail);
}我们可以想到另一个函数,它将使用上面的函数为每个y框生成HTML,并给每个类定义其宽度:
function toHtml(x, y) {
let i = 1;
return widths(x, y).map(w => `<span class="w${w}_${x}">${i++}<\/span>`)
.join("");
}剩下的就是定义相应的CSS和容器元素。
下面是一个允许您以交互方式定义x和y的片段,以实时方式显示结果:
function tail(x, y) {
let mod = y % x;
if (mod == 0) return []; // All items have size 1
if (x == 2 || y == 1) return [2]; // Last row consists of one item of size 2
if (x == 3) return [[2, 1, 2, 1], [2, 1]][mod-1];
if (x == 4) return [[2, 1, 1, 2, 2], [2, 2], [2, 1, 1]][mod-1];
}
function widths(x, y) {
// Get the special rows that have to appear at the very end
let arrTail = tail(x, y);
// Prepend the number of normal cells (all having size 1):
return Array(y - arrTail.length).fill(1).concat(arrTail);
}
function toHtml(x, y) {
let i = 1;
return widths(x, y).map(w => `<span class="w${w}_${x}">${i++}<\/span>`)
.join("");
}
// I/O management
let [inputX, inputY] = document.querySelectorAll("input");
let container = document.querySelector("#container");
function refresh() {
let x = +inputX.value;
let y = +inputY.value;
container.innerHTML = toHtml(x, y);
}
refresh();
document.addEventListener("input", refresh);#container > span {
box-sizing: border-box;
border: 1px solid;
display: inline-block;
text-align: center;
}
#container > span:nth-child(even) { background: #eee }
.w1_1, .w2_2 { width: 100% }
.w1_3 { width: 33.33% }
.w1_4 { width: 25%; }
.w2_3 { width: 66.66% }
.w2_4, .w1_2 { width: 50%; }Columns: <input type="number" min="1" max="4" value="4">
Items: <input type="number" min="1" value="7">
<p>
<div id="container"></div>
发布于 2020-02-03 22:27:17
与@trincot略有不同的方法。(我相信谁更优雅):
演示:https://codepen.io/Alexander9111/pen/povMXOG
HTML:
<input placeholder="enter number of cells"/>
<div id="holder">
</div>联署材料:
const holder = document.querySelector('#holder');
function calculateGrid(Y) {
const xMax=4;
let flag = void(0);
let remainder = Y % xMax;
let rows = Math.floor(Y / xMax, 0);
//console.log(rows, remainder);
if (Y > 1 && remainder == 1){
flag = rows - 1;
remainder = 2;
}
let output = [];
let temp = [];
let tempMax = 0;
for (let i=0; i<=rows; i++){
temp = [];
if (i == flag){
tempMax = (xMax-1);
} else if (i == rows){
tempMax = remainder;
} else {
tempMax = xMax;
}
for (let j=0; j<tempMax; j++){
temp.push(1);
}
for (let j=0; j<temp.length; j++){
if (temp.reduce((a,b)=>a+b) == xMax){
break;
} else {
temp[j] += 1;
}
}
output.push(temp);
}
return output;
}
function draw(grid){
holder.innerHTML = "";
num = 1;
for (let i=0; i<grid.length; i++){
let row = document.createElement('div');
row.id = "row"+i;
row.classList.add('row');
holder.appendChild(row);
for (let j=0; j<grid[i].length; j++){
let cell = document.createElement('div');
cell.id = "row"+i+"_col"+j;
cell.classList.add('cell');
cell.classList.add('w'+grid[i][j]);
cell.innerText = num;
row.appendChild(cell);
num +=1;
}
}
}
const input = document.querySelector('input');
input.addEventListener('change', (e) => {
const val = parseInt(e.target.value);
const grid = calculateGrid(val);
console.log(grid);
draw(grid);
});https://stackoverflow.com/questions/60046130
复制相似问题