feat: Added expected and maximum number of comparisons
This commit is contained in:
parent
a15965c9ba
commit
56bab8f861
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,6 +3,9 @@
|
||||||
# personal notes
|
# personal notes
|
||||||
Notes.md
|
Notes.md
|
||||||
|
|
||||||
|
# hacky upload script
|
||||||
|
lib/pushToMongoManually.js
|
||||||
|
|
||||||
# convenience old folder
|
# convenience old folder
|
||||||
pages/.old/*
|
pages/.old/*
|
||||||
pages/.old
|
pages/.old
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { DisplayAsMarkdown } from './displayAsMarkdown'
|
||||||
import { CreateTableWithDistances } from './findPaths'
|
import { CreateTableWithDistances } from './findPaths'
|
||||||
import { TextAreaForJson } from "./textAreaForJson"
|
import { TextAreaForJson } from "./textAreaForJson"
|
||||||
import { pushToMongo } from "./pushToMongo.js"
|
import { pushToMongo } from "./pushToMongo.js"
|
||||||
|
import { maxMergeSortSteps, expectedNumMergeSortSteps } from "./utils.js"
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
let increasingList = (n) => Array.from(Array(n).keys())
|
let increasingList = (n) => Array.from(Array(n).keys())
|
||||||
|
@ -40,10 +41,6 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
// State
|
// State
|
||||||
let initialListOfElements = listOfElementsForView.map((element, i) => ({ ...element, id: i }))
|
let initialListOfElements = listOfElementsForView.map((element, i) => ({ ...element, id: i }))
|
||||||
let initialPosList = increasingList(listOfElementsForView.length) // [0,1,2,3,4]
|
let initialPosList = increasingList(listOfElementsForView.length) // [0,1,2,3,4]
|
||||||
//let listOfElements = listOfElementsForView.map((element, i) => ({...element, id: i}))
|
|
||||||
//let list = increasingList(listOfElementsForView.length) // [0,1,2,3,4]
|
|
||||||
|
|
||||||
//let initialComparePair = [list[list.length-2], list[list.length-1]]
|
|
||||||
let initialComparePair = [initialPosList[initialPosList.length - 2], initialPosList[initialPosList.length - 1]]
|
let initialComparePair = [initialPosList[initialPosList.length - 2], initialPosList[initialPosList.length - 1]]
|
||||||
let initialSliderValue = 1
|
let initialSliderValue = 1
|
||||||
let initialReasoning = ''
|
let initialReasoning = ''
|
||||||
|
@ -54,6 +51,13 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
let initialShowAdvancedOptions = false
|
let initialShowAdvancedOptions = false
|
||||||
let initialShowComparisons = false
|
let initialShowComparisons = false
|
||||||
let initialShowChangeDataSet = false
|
let initialShowChangeDataSet = false
|
||||||
|
let initialNumSteps = 0;
|
||||||
|
let maxSteps = maxMergeSortSteps(listOfElementsForView.length)
|
||||||
|
let expectedSteps = expectedNumMergeSortSteps(listOfElementsForView.length)
|
||||||
|
|
||||||
|
//let listOfElements = listOfElementsForView.map((element, i) => ({...element, id: i}))
|
||||||
|
//let list = increasingList(listOfElementsForView.length) // [0,1,2,3,4]
|
||||||
|
//let initialComparePair = [list[list.length-2], list[list.length-1]]
|
||||||
|
|
||||||
const [listOfElements, setListOfElements] = useState(initialListOfElements)
|
const [listOfElements, setListOfElements] = useState(initialListOfElements)
|
||||||
const [posList, setPosList] = useState(initialPosList)
|
const [posList, setPosList] = useState(initialPosList)
|
||||||
|
@ -72,6 +76,8 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
let [showAdvancedOptions, changeShowAdvanceOptions] = useState(initialShowAdvancedOptions);
|
let [showAdvancedOptions, changeShowAdvanceOptions] = useState(initialShowAdvancedOptions);
|
||||||
let [showComparisons, changeShowComparisons] = useState(initialShowComparisons);
|
let [showComparisons, changeShowComparisons] = useState(initialShowComparisons);
|
||||||
let [showChangeDataSet, changeshowChangeDataSet] = useState(initialShowChangeDataSet);
|
let [showChangeDataSet, changeshowChangeDataSet] = useState(initialShowChangeDataSet);
|
||||||
|
let [numSteps, increaseNumSteps] = useState(initialNumSteps);
|
||||||
|
|
||||||
|
|
||||||
let restart = (posList) => {
|
let restart = (posList) => {
|
||||||
setToComparePair([posList[posList.length - 2], posList[posList.length - 1]])
|
setToComparePair([posList[posList.length - 2], posList[posList.length - 1]])
|
||||||
|
@ -195,6 +201,7 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
|
|
||||||
setSliderValue(1)
|
setSliderValue(1)
|
||||||
setReasoning('')
|
setReasoning('')
|
||||||
|
increaseNumSteps(numSteps+1)
|
||||||
if (successStatus) {
|
if (successStatus) {
|
||||||
let jsObject = nicelyFormatLinks(quantitativeComparisons, listOfElements)
|
let jsObject = nicelyFormatLinks(quantitativeComparisons, listOfElements)
|
||||||
pushToMongo(jsObject)
|
pushToMongo(jsObject)
|
||||||
|
@ -216,6 +223,7 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
<h1 className="text-6xl font-bold">
|
<h1 className="text-6xl font-bold">
|
||||||
Utility Function Extractor
|
Utility Function Extractor
|
||||||
</h1>
|
</h1>
|
||||||
|
<p>{`${numSteps} out of ~${expectedSteps} (max ${maxSteps}) comparisons`}</p>
|
||||||
|
|
||||||
<div className={`${isListOrdered ? "hidden" : ""}`}>
|
<div className={`${isListOrdered ? "hidden" : ""}`}>
|
||||||
<div className="flex flex-wrap items-center max-w-4xl sm:w-full mt-10">
|
<div className="flex flex-wrap items-center max-w-4xl sm:w-full mt-10">
|
||||||
|
@ -237,17 +245,17 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
<label>
|
<label>
|
||||||
{`... is `}
|
{`... is `}
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
className="text-center text-blueGray-600 bg-white rounded text-lg border-0 shadow outline-none focus:outline-none focus:ring w-8/12 h-10 m-2"
|
className="text-center text-blueGray-600 bg-white rounded text-lg border-0 shadow outline-none focus:outline-none focus:ring w-8/12 h-10 m-2"
|
||||||
value={sliderValue}
|
value={sliderValue}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
//console.log(event)
|
//console.log(event)
|
||||||
//console.log(event.target.value)
|
//console.log(event.target.value)
|
||||||
setSliderValue(event.target.value)
|
setSliderValue(event.target.value)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
{`times as valuable as ...`}
|
{`times as valuable as ...`}
|
||||||
</label>
|
</label>
|
||||||
|
@ -279,8 +287,8 @@ export default function ComparisonView({ listOfElementsForView }) {
|
||||||
<label className="">
|
<label className="">
|
||||||
Reasoning (optional):
|
Reasoning (optional):
|
||||||
<textarea className="mt-2 px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border-0 shadow outline-none focus:outline-none focus:ring w-full"
|
<textarea className="mt-2 px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border-0 shadow outline-none focus:outline-none focus:ring w-full"
|
||||||
value={reasoning}
|
value={reasoning}
|
||||||
onChange={(event) => setReasoning(event.target.value)}
|
onChange={(event) => setReasoning(event.target.value)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<br />
|
<br />
|
||||||
|
|
54
lib/utils.js
54
lib/utils.js
|
@ -8,37 +8,63 @@ export const transformSliderValueToPracticalValue = id
|
||||||
export const _transformSliderValueToActualValue = value => 10 ** value //>= 2 ? Math.round(10 ** value) : Math.round(10 * 10 ** value) / 10
|
export const _transformSliderValueToActualValue = value => 10 ** value //>= 2 ? Math.round(10 ** value) : Math.round(10 * 10 ** value) / 10
|
||||||
export const toLocale = x => Number(x).toLocaleString()
|
export const toLocale = x => Number(x).toLocaleString()
|
||||||
export const truncateValueForDisplay = value => {
|
export const truncateValueForDisplay = value => {
|
||||||
if(value > 10){
|
if (value > 10) {
|
||||||
return Number(Math.round(value).toPrecision(2))
|
return Number(Math.round(value).toPrecision(2))
|
||||||
}else if(value > 1){
|
} else if (value > 1) {
|
||||||
return Math.round(value * 10) / 10
|
return Math.round(value * 10) / 10
|
||||||
} else if(value < 1){
|
} else if (value < 1) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const _transformSliderValueToPracticalValue = value => truncateValueForDisplay(transformSliderValueToActualValue(value))
|
export const _transformSliderValueToPracticalValue = value => truncateValueForDisplay(transformSliderValueToActualValue(value))
|
||||||
|
|
||||||
export function numToAlphabeticalString(num){
|
export function numToAlphabeticalString(num) {
|
||||||
// https://stackoverflow.com/questions/45787459/convert-number-to-alphabet-string-javascript/45787487
|
// https://stackoverflow.com/questions/45787459/convert-number-to-alphabet-string-javascript/45787487
|
||||||
num=num+1
|
num = num + 1
|
||||||
var s = '', t;
|
var s = '', t;
|
||||||
while (num > 0) {
|
while (num > 0) {
|
||||||
t = (num - 1) % 26;
|
t = (num - 1) % 26;
|
||||||
s = String.fromCharCode(65 + t) + s;
|
s = String.fromCharCode(65 + t) + s;
|
||||||
num = (num - t)/26 | 0;
|
num = (num - t) / 26 | 0;
|
||||||
}
|
}
|
||||||
return `#${s}` || undefined;
|
return `#${s}` || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatLargeOrSmall (num) {
|
export function formatLargeOrSmall(num) {
|
||||||
if(num > 1){
|
if (num > 1) {
|
||||||
return toLocale(truncateValueForDisplay(num))
|
return toLocale(truncateValueForDisplay(num))
|
||||||
}else if(num > 0){
|
} else if (num > 0) {
|
||||||
return num.toFixed(-Math.floor(Math.log(num)/Math.log(10))+1);
|
return num.toFixed(-Math.floor(Math.log(num) / Math.log(10)) + 1);
|
||||||
}else if(num < -1){
|
} else if (num < -1) {
|
||||||
return num.toFixed(-Math.floor(Math.log(-num)/Math.log(10))+1);
|
return num.toFixed(-Math.floor(Math.log(-num) / Math.log(10)) + 1);
|
||||||
}else{
|
} else {
|
||||||
return toLocale(num)//return "~0"
|
return toLocale(num)//return "~0"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const firstFewMaxMergeSortSequence = [0, 0, 1, 3, 5, 8, 11, 14, 17, 21, 25, 29, 33, 37, 41, 45, 49, 54, 59, 64, 69, 74, 79, 84, 89, 94, 99, 104, 109, 114, 119, 124, 129, 135, 141, 147, 153, 159, 165, 171, 177, 183, 189, 195, 201, 207, 213, 219, 225, 231, 237, 243, 249, 255, 261, 267, 273, 279, 285]
|
||||||
|
|
||||||
|
export function maxMergeSortSteps(n) {
|
||||||
|
if (n < firstFewMaxMergeSortSequence.length) {
|
||||||
|
return firstFewMaxMergeSortSequence[n]
|
||||||
|
} else {
|
||||||
|
return maxMergeSortSteps(Math.floor(n / 2)) + maxMergeSortSteps(Math.ceil(n / 2)) + n - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function expectedNumMergeSortSteps(n) {
|
||||||
|
// https://cs.stackexchange.com/questions/82862/expected-number-of-comparisons-in-a-merge-step
|
||||||
|
// n-2 for each step, so (n-2) + (n-2)/2 + (n-2)/4 + ...
|
||||||
|
// ~ 2*(n-2) -1 = 2*n - 3
|
||||||
|
if (n == 0) {
|
||||||
|
return 0
|
||||||
|
} else if (n == 1) {
|
||||||
|
return 0
|
||||||
|
} else if (n == 2) {
|
||||||
|
return 1
|
||||||
|
} else if (n == 3) {
|
||||||
|
return 2
|
||||||
|
} else {
|
||||||
|
return Math.ceil((n ** 2) / (n + 2)) + expectedNumMergeSortSteps(Math.ceil(n / 2))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user