Public
Edited
Dec 30, 2022
1 star
ЕГЭ по Информатике. Вариант №01092023, 2023г. Составил Евгений Джобс.ЕГЭ по Информатике. Вариант №16012023, 2023г. Составил Марат Ишимов.Оптимизация перебораDynamic Programming Notes
Automatic Recursive Memoization
Problem with recursion and memoizationОрграф для задачи №13 ЕГЭ по информатике.Dependencies in a dynamic-programming problemГраф для задачи №1 ЕГЭ по информатике.ЕГЭ по Информатике. Демоверсия ФИПИ 2023. Исходный код на JavaScript.Sorting AlgorithmsMerge SortКак работает сортировка слияниемРешаем задачу коммивояжёра простым переборомЗадача № 13 из демоверсии ЕГЭ 2022Tower of HanoiЗадача про охрану периметраЕГЭ по Информатике. Задача №25. Обработка целочисленных данных. Поиск делителей. №3160 с сайта К.Ю. Полякова.Rabbit in the HoleПробный вариант ЕГЭ от /dev/infНекрыловские вариантыGraphs: breadth-first searchEfficient Graph SearchTowers of HanoiЕГЭ по Информатике Пробный вариант от /dev/infЕГЭ по Информатике. Задача №24. Обработка символьной информации. Демоверсия ФИПИ 2022.ЕГЭ по Информатике. Задача №3. Базы данных. Демоверсия ФИПИ 2022.ЕГЭ по Информатике. Задача №9. Обработка чисел в электронных таблицах. №4709 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №9. Обработка чисел в электронных таблицах. №4346 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №9. Обработка чисел в электронных таблицах. №4338 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №9. Обработка чисел в электронных таблицах. №4342 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №9. Обработка чисел в электронных таблицах. №4337 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №9. Обработка чисел в электронных таблицах. Демоверсия ФИПИ 2022.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №377 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №3835 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №2986 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №2238 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №4027 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №1069 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. №3480 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №15. Истинность логического выражения. Демоверсия ФИПИ 2022.ЕГЭ по Информатике. Задача №24. Обработка символьной информации. Демоверсия ФИПИ 2022.ЕГЭ по Информатике. Задача №23. Динамическое программирование. Демоверсия ФИПИ 2022.Рекурсия. Задача Фибоначчи о кроликах.ЕГЭ по Информатике. Задача №16. Рекурсивные алгоритмы. Демоверсия ФИПИ 2022.Canvas to GIF для исполнителя «Редактор» из ЕГЭ по ИнформатикеЕГЭ по Информатике. Задача №2. Таблицы истинности логических выражений. №1627 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №4. Двоичное кодирование, условие Фано. №1670 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №2. Таблицы истинности логических выражений. №1613 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №4. Двоичное кодирование, условие Фано. №119 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». Демоверсия ФИПИ 2022.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». №4163 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». №3463 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». №3838 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». №4632 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». №3424 с сайта К.Ю. Полякова.ЕГЭ по Информатике. Задача №12. Исполнитель «Редактор». №4491 с сайта К.Ю. Полякова.
Insert cell
Insert cell
Insert cell
function fib(n) {
return n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
}
Insert cell
memfib = memrec(fib)
Insert cell
a = perf(fib, 35)
Insert cell
b = perf(memfib, 35)
Insert cell
Insert cell
function fibbish(a, b) {
return a*b + ((a >= 1 && b >= 1) ? fibbish(a-1, b-2) + fibbish(a-2, b-1) : 0);
}
Insert cell
memfibbish = memrec(fibbish)
Insert cell
c = perf(fibbish, 39,39)
Insert cell
d = perf(memfibbish, 39, 39)
Insert cell
Insert cell
function squared(n){ return n*n; }
Insert cell
Insert cell
memsquared = {
const cache = {};
return function memsquared(n){
if (!cache.hasOwnProperty(n)) {
cache[n] = squared(n);
}
return cache[n];
}
}
Insert cell
Insert cell
function fiblog(n, log = []) {
// keep track of each time fiblog is called
log.push(`fiblog(${n}, log)`);
const val = n <= 1 ? 1 : fiblog(n - 1, log).val + fiblog(n - 2, log).val;
return {val, log};
}
Insert cell
fiblog(1)
Insert cell
fiblog(2)
Insert cell
fiblog(3)
Insert cell
fiblog(10)
Insert cell
fiblog(30)
Insert cell
Insert cell
memfibdumb = {
const cache = {};
return function memfibdumb(n, log = []){
if (!cache.hasOwnProperty(n)) {
cache[n] = fiblog(n, log);
}
return cache[n];
};
}
Insert cell
memfibdumb(1)
Insert cell
memfibdumb(2)
Insert cell
memfibdumb(10)
Insert cell
memfibdumb(30)
Insert cell
Insert cell
// I'm creating a new memoized function each time to
// demonstrate how the cache is built up - otherwise
// subsequent calls to the same function would
// benefit from the memoization of previous calls!
function memfibmanual(){
const cache = {};
return function memfibmanual(n, log = []){
// keep track of each time fiblog is called
log.push(`memfibmanual(${n}, log)`);
if (n <= 1) return {val: 1, log};
if(!cache.hasOwnProperty(n)) {
cache[n] = memfibmanual(n-1, log).val + memfibmanual(n-2, log).val;
}
return {val: cache[n], log};
};
}

Insert cell
memfibmanual()(1)
Insert cell
memfibmanual()(2)
Insert cell
memfibmanual()(3)
Insert cell
memfibmanual()(10)
Insert cell
memfibmanual()(30)
Insert cell
Insert cell
Insert cell
// To be used in combination with memrec below.
// To memoize functions with multiple parameters, a simple key => value map won't do.
// Instead we want a kind of map that takes a list of parameters as the key for its
// get and set methods. That is what this class does.
// (If you only pass JSON-serializable objects to a function, you could get away
// with using one map and applying JSON.stringify to the arguments instead)
// TODO: make it possible to only remember the last N results
class ParamCache {
constructor() {
this.cache = new Map();
}

// walk through our cache tree - if our params are not present,
// create the needed maps to initiate the tree.
walkparams(params) {
let {cache} = this;
// Note that the first param is always the recursive function itself,
// so we can skip that. We stop just before the last parameter, as
// that is the one we use to determine if the tree has already
// cached a previous result or not.
for(let i = 1; i < params.length-1; i++) {
let nextcache = cache.get(params[i]);
if (nextcache === undefined) {
for (let j = i; j < params.length-1; j++) {
nextcache = new Map();
cache.set(params[j], nextcache);
cache = nextcache;
}
break;
} else {
cache = nextcache
}
}
return cache;
}

get(params) {
const cache = this.walkparams(params);
// a function may return `undefined` as a return value,
// which we should cache. To indicate this we return an
// array. If the get was successful, it has one entry.
// If not, it's empty.
let value = []
if (cache.has(params[params.length-1])) value.push(cache.get(params[params.length-1]))
return value;
}

set(params, value) {
const cache = this.walkparams(params);
cache.set(params[params.length-1], value);
}
}
Insert cell
function memrec(fn) {
const name = fn.name;
const src = fn.toString();
// We want to avoid naming collisions with original source code,
// so we use a long string of random chars for our function name.
// 32**64 means there's a chance of roughly one in 10 ** 96 of
// a naming collision.
// I think we're good.
let hash = ""
for(let i = 0; i < 64;i++) { hash += (Math.random()*32|0).toString(32); }
let fn_name = "fn_" + hash;
// this is a terrible way to detect where the parameters start and end.
// Basically, if someone uses a default value with a string that has a
// ")" in it, or has a lambda as a default value, or anything else
// with an early closing parenthesis in it, this breaks.
let i = src.indexOf("(");
let j = src.indexOf(")", i);

// A pure function that takes no parameters is easy to memoize.
// (but why would anyone be memoizing this?)
if (i+1 === j) {
const v = fn();
return () => v;
}

// First we convert recursive function into one that has the recursive calls
// to itself replaced with calls to a function that has to be passed explicitly.
// For example, from:
//
// function fib(n) {
// return n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
// }
//
// to
//
// const newfn = function(cb, n) {
// return n <= 1 ? 1 : cb(cb, n - 1) + cb(cb, n - 2);
// };
//
// That might seem a bit silly at first, but this allows us to make a memoized
// version of it later.
// Count number of parameters.
// Maybe slightly less fragile in the face of default values with strings with commas
// Does not handle every case, breaks when we start embedding strings in strings with
// single quotes, double quotes and backticks, not to mention escape codes for example.
// Split string by commas, but ignore commas inside quotes
// https://stackoverflow.com/questions/23582276/split-string-by-comma-but-ignore-commas-inside-quotes#comment71514557_23582323
const paramRegex = /,(?=(?:(?:[^'"]*(?:'|")){2})*[^'"]*$)/;
let params = src.substring(i+1, j).split(paramRegex);

// we're going to assume that the first time we see "{" in our source
// after the parameters it will be the start of the function body, and
// that the last "}" ends it.
const src_body = src.substring(src.indexOf("{", j) + 1, src.lastIndexOf("}"))
// find and replace all recursive calls with the new function name, and insert the new function as
// the first parameter.
const fnRegexp = new RegExp(`([;:{\\s])${name}(\\s*\\()`, 'g');
const rec_body = src_body.replace(fnRegexp, `$1${fn_name}(${fn_name}, `);

// create a new function
params.unshift(fn_name);
params.push(rec_body);
const newfn = new Function(...params);
// Now we're ready to create a memoized version. The trick is to create a memoized
// wrapper cachefn that calls newfn, while passing itself instead of newfn as the
// function to be called to newfn.
// What this means is that newfn will call cachefn when doing recursion. If the
// new parameters have a result that is memoized, cachefn will return it. If not,
// it will call newfn with the changed parameters. This is a form of mutual
// recursion that results in the cache lookup being interjected in the function
// call at the right position.
const cache = new ParamCache();
const cachefn = (...args) => {
let v = cache.get(args);
if (!v.length) {
v[0] = newfn(...args);
cache.set(args, v[0]);
}
return v[0];
}
// we don't want to expose all this weirdness of mutual-recursive-self-passing,
// so we create a final wrapper that accepts the original arguments and return it
return (...args) => {
return cachefn(cachefn, ...args);
};
}
Insert cell
perf = (fn, ...args) => {
var t0 = performance.now();
var result = fn(...args);
var time = performance.now() - t0;
return { result, time };
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more