Created
March 27, 2018 09:21
-
-
Save zhirzh/aa02be34407eebe8998d2ff35946cdc9 to your computer and use it in GitHub Desktop.
Negative Indexing Multi Arrays in C/++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const cppCode = document.getElementById("cpp-template").innerHTML; | |
document.getElementById("cpp").innerHTML = cppCode.replace(/\s{2,}/g, ""); | |
const app = new Vue({ | |
el: "#app", | |
data: { | |
counterMode: false, | |
dimensionCount: { value: 2, prevValue: 2 }, | |
dimensionSizes: [{ value: 2, prevValue: 2 }, { value: 3, prevValue: 3 }], | |
defaultDimensionSize: { value: 2, prevValue: 2 }, | |
queries: [{ value: 0, prevValue: 0 }, { value: 2, prevValue: 2 }], | |
defaultQuery: { value: 0, prevValue: 0 } | |
}, | |
computed: { | |
cellCounts() { | |
// C_k = D_1 * D_2 ... D_k | |
// C_k = C_0 / S_k | |
return this.dimensionSizeValues | |
.slice(1) | |
.reduce((acc, x) => acc.concat(acc[acc.length - 1] * x), [ | |
this.dimensionSizeValues[0] | |
]); | |
}, | |
cellStrides() { | |
// S_k = D_(k+1) * D_(k+2) ... D_n | |
// S_k = C_0 / C_k | |
return this.cellCounts.map(count => this.dataCount / count); | |
}, | |
dimensionSizeValues() { | |
return this.dimensionSizes.map(d => d.value); | |
}, | |
numbers() { | |
const numbers = []; | |
for (let i = 0; i < this.dataCount; i++) { | |
numbers.push(10000 + (i + 1)); | |
} | |
return numbers; | |
}, | |
queryMatches() { | |
// M_k = ((Q_1 * S_1) + (Q_2 * S_2) ... (Q_k * S_k)) / S_k | |
return this.queries.map(q => q.value).reduce((acc, _, i) => { | |
return acc.concat( | |
this.queries | |
.slice(0, i + 1) | |
.reduce((acc2, q, j) => acc2 + q.value * this.cellStrides[j], 0) / | |
this.cellStrides[i] | |
); | |
}, []); | |
}, | |
dataCount() { | |
// C_0 = D_1 * D_2 ... D_n | |
return this.dimensionSizeValues.reduce((acc, d) => acc * d); | |
} | |
}, | |
methods: { | |
/** | |
* Convert input to a clamped number | |
* @param {string} x | |
* @param {number[]} range | |
* @param {string} range[].lo - Lower limit of range | |
* @param {string} range[].hi - Upper limit of range | |
*/ | |
toNumberClamped(x, [lo, hi]) { | |
x = Number(x); | |
if (isNaN(x)) { | |
return null; | |
} | |
if (x < lo) { | |
return lo; | |
} | |
if (x > hi) { | |
return hi; | |
} | |
return x; | |
}, | |
/** | |
* Update number of dimensionSizes | |
* @param {event} e | |
*/ | |
updateDimensionCount(e) { | |
const currDimensionCount = this.dimensionCount; | |
const nextDimensionCountValue = this.toNumberClamped( | |
e.currentTarget.value, | |
[1, 5] | |
); | |
if (nextDimensionCountValue === null) { | |
currDimensionCount.value = currDimensionCount.prevValue; | |
} else { | |
currDimensionCount.prevValue = nextDimensionCountValue; | |
currDimensionCount.value = nextDimensionCountValue; | |
} | |
this.updateDimensionSizes(); | |
this.updateQueries(); | |
}, | |
/** | |
* Update dimensionSizes | |
*/ | |
updateDimensionSizes() { | |
const nextDimensions = []; | |
for (let i = 0; i < this.dimensionCount.value; i++) { | |
nextDimensions.push( | |
this.dimensionSizes[i] || Object.assign({}, this.defaultDimensionSize) | |
); | |
} | |
this.dimensionSizes = nextDimensions; | |
}, | |
/** | |
* Update `ith` dimension | |
* @param {number} i - Index of dimension | |
* @param {event} e | |
*/ | |
updateDimensionSize(i, e) { | |
const dimension = this.dimensionSizes[i]; | |
const nextDimensionValue = this.toNumberClamped(e.currentTarget.value, [ | |
1, | |
4 | |
]); | |
if (nextDimensionValue === null) { | |
dimension.value = dimension.prevValue; | |
} else { | |
dimension.prevValue = nextDimensionValue; | |
dimension.value = nextDimensionValue; | |
} | |
}, | |
/** | |
* Update queries | |
*/ | |
updateQueries() { | |
const nextQueries = []; | |
for (let i = 0; i < this.dimensionCount.value; i++) { | |
nextQueries.push( | |
this.queries[i] || Object.assign({}, this.defaultQuery) | |
); | |
} | |
this.queries = nextQueries; | |
}, | |
/** | |
* Update `ith` query | |
* @param {number} i - Index of query | |
* @param {event} e | |
*/ | |
updateQuery(i, e) { | |
const query = this.queries[i]; | |
console.log(e.currentTarget.value); | |
const nextQueryValue = this.toNumberClamped(e.currentTarget.value, [ | |
-Infinity, | |
Infinity | |
]); | |
if (nextQueryValue === null) { | |
query.value = query.prevValue; | |
} else { | |
query.prevValue = nextQueryValue; | |
query.value = nextQueryValue; | |
} | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
<link rel="stylesheet" type="text/css" href="style.css"> | |
</head> | |
<body> | |
<div id="app"> | |
<!-- <form> | |
<div> | |
Counter Mode: | |
<input type="checkbox" onfocus="this.select()" v-model="counterMode" /> | |
</div> | |
</form> --> | |
<div class="code"> | |
<pre id="cpp"></pre> | |
</div> | |
<div class="memory-container"> | |
<table class="memory"> | |
<tr v-for="(count, i) in cellCounts"> | |
<td | |
:class="['memory-cell', j-1 === queryMatches[i] && 'query']" | |
v-for="j in count" :colspan="cellStrides[i]" | |
> | |
<span v-if="counterMode">{{j}}</span> | |
<span v-else>{{(j-1) % dimensionSizeValues[i]}}</span> | |
</td> | |
</tr> | |
<tr> | |
<td | |
:class="['memory-cell', 'memory-data', i === queryMatches[dimensionCount.value - 1] && 'query']" | |
v-for="(x, i) in numbers"> | |
{{x}} | |
</td> | |
</tr> | |
</table> | |
</div> | |
</div> | |
<template id="cpp-template"> | |
// Enter number of dimensions | |
<br /> | |
int N = <input | |
type="number" | |
min="1" | |
max="5" | |
onfocus="this.select()" | |
v-model.number="dimensionCount.value" | |
v-on:input="updateDimensionCount" | |
/>; | |
<br /> | |
<br /> | |
// Enter dimension sizes | |
<br /> int arr | |
<span v-for="(d, i) in dimensionSizes"> | |
[ | |
<input | |
type="number" | |
min="1" | |
max="5" | |
onfocus="this.select()" | |
v-model.number="d.value" | |
v-on:input="updateDimensionSize(i, $event)" | |
/> | |
] | |
</span> = { | |
<span v-if="numbers.length <= 5"> | |
<span v-for="(n, i) in numbers"> | |
<span>{{n}}</span> | |
<span v-if="i+1 < numbers.length">, </span> | |
</span> | |
}; | |
</span> | |
<span v-else> | |
<span v-for="(n, i) in numbers.slice(0, 3)"> | |
<span>{{n}}</span> | |
<span v-if="i+1 < numbers.length">, </span> | |
</span> | |
... | |
, <span>{{numbers[numbers.length - 1]}}</span> | |
}; | |
</span> | |
<br /> | |
<br /> | |
// Run a query on the array | |
<br /> | |
cout << arr | |
<span v-for="(q, i) in queries"> | |
[ | |
<input | |
type="number" | |
onfocus="this.select()" | |
v-model.number="q.value" | |
:style="{width: ((q.value.toString().length || 1) * 13) + 'px'}" | |
/> | |
] | |
</span>; | |
</template> | |
<script src="app.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global */ | |
* { | |
padding: 0; | |
margin: 0; | |
box-sizing: border-box; | |
font-family: sans-serif; | |
font-size: 20px; | |
} | |
input[type=number] { | |
box-sizing: content-box; | |
width: 13px; | |
border: none; | |
box-shadow: 0 2px 0 gray; | |
outline: none; | |
padding: 0 6px; | |
text-align: center; | |
} | |
input[type=number]::-webkit-outer-spin-button, | |
input[type=number]::-webkit-inner-spin-button { | |
-webkit-appearance: none; | |
margin: 0; | |
} | |
input[type=number] { | |
-moz-appearance: textfield; | |
} | |
/* #app */ | |
#app { | |
padding: 20px; | |
} | |
/* .code */ | |
.code { | |
margin: 30px 0; | |
} | |
.code * { | |
font-family: monospace; | |
} | |
.code pre { | |
line-height: 32px; | |
} | |
.code input { | |
background-color: #f0f0f0; | |
} | |
/* .memory */ | |
.memory-container { | |
overflow-x: auto; | |
} | |
.memory { | |
border-collapse: collapse; | |
} | |
.memory-cell { | |
/* text-align: center; */ | |
padding: 10px; | |
background-color: #ccc; | |
border: 12px solid #eee; | |
} | |
.memory-cell.query { | |
background-color: #666; | |
color: white; | |
} | |
.memory-cell.memory-data { | |
background-color: #aaa; | |
} | |
.memory-cell.memory-data.query { | |
background-color: #222; | |
color: white; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment