La implementación de la biblioteca babilónica

En este artículo aprenderá todo sobre la biblioteca de Babilonia, y lo más importante: cómo recrearla y, de hecho, cualquier biblioteca.

Comencemos con las citas de la Biblioteca Babilónica de Luis Borges .

Cita
“El universo, algunos lo llaman la Biblioteca, consiste en una gran cantidad, posiblemente infinita, de galerías hexagonales, con amplias cámaras de ventilación encerradas por rieles bajos. Desde cada hexágono son visibles dos pisos superiores y dos inferiores, hasta el infinito ".

“Una biblioteca es una bola, cuyo centro exacto está en uno de los hexágonos, y la superficie es inaccesible. En cada pared de cada hexágono hay cinco estantes, en cada estante hay treinta y dos libros del mismo formato, cada libro tiene cuatrocientas diez páginas, cada página tiene cuarenta líneas, cada línea contiene aproximadamente ochenta letras negras. Hay letras en el lomo del libro, pero no definen ni presagian lo que dirán las páginas. Esta discrepancia, lo sé, una vez pareció misteriosa.


Si ingresa un hexágono aleatorio, suba a cualquier pared, mire cualquier estante y tome el libro que más le guste, entonces es más probable que se enoje. Después de todo, esperabas descubrir el significado de la vida allí, pero viste un extraño conjunto de personajes. ¡Pero no te enfades tan rápido! La mayoría de los libros no tienen sentido, porque son una búsqueda combinatoria de todas las variantes posibles de veinticinco caracteres ( es este alfabeto el que Borges usó en su biblioteca, pero luego el lector descubrirá que puede haber cualquier número de caracteres en la biblioteca ). La ley principal de la biblioteca es que no hay dos libros absolutamente idénticos, por lo tanto, su número es finito, y la biblioteca también terminará algún día. Borges creía que la biblioteca es periódica:

Cita
“Quizás el miedo y la vejez me están engañando, pero creo que la raza humana, la única, está cerca de la extinción, y la Biblioteca sobrevivirá: iluminada, deshabitada, infinita, absolutamente inmóvil, llena de volúmenes preciosos, inútil, incorrupto, misterioso. Acabo de escribir sin fin. No expresé esta palabra por amor a la retórica; Creo que es lógico suponer que el mundo es interminable. Aquellos que lo consideran limitado admiten que en algún lugar en los corredores, escaleras y hexágonos pueden terminar por alguna razón desconocida, tal suposición es absurda. Quienes lo imaginan sin límites olvidan que el número de libros posibles es limitado. Me atrevo a proponer una solución a este antiguo problema: la biblioteca es ilimitada y periódica. Si el vagabundo eterno se embarcó en un viaje en cualquier dirección, podría verificar después de siglos que los mismos libros se repiten en el mismo lío (que, cuando se repite, se convierte en orden - Orden). Esta graciosa esperanza ilumina mi soledad ".


En comparación con las tonterías, hay muy pocos libros cuyos contenidos una persona pueda entender al menos de alguna manera, pero esto no cambia el hecho de que la biblioteca contiene todos los textos que fueron y serán inventados por una persona. Y además, desde la infancia estás acostumbrado a considerar algunas secuencias de símbolos significativas, mientras que otras no. De hecho, en el contexto de la biblioteca, no hay diferencia entre ellos. Pero lo que tiene sentido tiene un porcentaje mucho más bajo, y lo llamamos lenguaje. Este es un medio de comunicación entre las personas. Cualquier lenguaje contiene solo unas pocas decenas de miles de palabras, de las cuales sabemos el 70% de la fuerza, por lo tanto, resulta que no podemos interpretar la mayor parte de la búsqueda combinatoria de libros. Y alguien sufre de apofenia e incluso en conjuntos aleatorios de personajes ve un significado oculto. ¡Pero esta es una buena idea para la esteganografía ! Bueno, sigo discutiendo este tema en los comentarios.

Antes de continuar con la implementación de esta biblioteca, te sorprenderé con un hecho interesante: si quieres recrear la biblioteca babilónica de Louis Borges, no tendrás éxito, porque sus volúmenes exceden el volumen del Universo visible 10 ^ 611338 (!) Veces. Y sobre lo que sucederá en bibliotecas aún más grandes, incluso tengo miedo de pensar.

Implementación de la biblioteca


Descripción del módulo


Nuestra pequeña introducción ha terminado. Pero no carece de sentido: ahora entiendes cómo es la biblioteca de Babilonia, y seguir leyendo solo será más interesante. Pero me alejaré de la idea original, quería crear una biblioteca "universal", que se discutirá más adelante. Escribiré en JavaScript en Node.js. ¿Qué debería poder hacer la biblioteca?
  • Encuentre rápidamente el texto deseado y muestre su ubicación en la biblioteca
  • Definir el título de un libro.
  • Encuentra un libro con el título correcto rápidamente

Además, debe ser universal, es decir cualquiera de los parámetros de la biblioteca se puede cambiar si quiero. Bueno, creo que primero mostraré el código completo del módulo, lo analizaremos en detalle, veremos cómo funciona y diré algunas palabras. Repositorio de Github

El archivo principal es index.js, toda la lógica de la biblioteca se describe allí, explicaré el contenido de este archivo.

let sha512 = require(`js-sha512`); 

Conectamos el módulo que implementa el algoritmo de hash sha512 . Puede parecerle extraño, pero igual nos será útil.
¿Cuál es la salida de nuestro módulo? Devuelve una función, una llamada a la que devolverá un objeto de biblioteca con todos los métodos necesarios. Podríamos devolverlo de inmediato, pero luego administrar la biblioteca no sería tan conveniente cuando pasáramos parámetros a la función y obtuviéramos la biblioteca "necesaria". Esto nos permitirá crear una biblioteca "universal". Como trato de escribir en estilo ES6, mi función de flecha acepta un objeto como parámetros, que posteriormente se desestructurarán en las variables necesarias:

 module.exports = ({ lengthOfPage = 4819, lengthOfTitle = 31, digs = '0123456789abcdefghijklmnopqrstuvwxyz', alphabet = ', .', wall = 5, shelf = 7, volume = 31, page = 421, } = {}) => { // ... }; 

Ahora repasemos los parámetros. Como los parámetros numéricos estándar, decidí elegir números primos, porque me pareció que sería más interesante.

  • lengthOfPage - número, número de caracteres en una página. El valor predeterminado es 4819. Si factorizamos este número, obtenemos 61 y 79. 61 líneas de 79 caracteres, o viceversa, pero prefiero la primera opción.
  • lengthOfTitle : número, número de caracteres en el título del título del libro.
  • excavaciones : una cadena, posibles dígitos de un número con una base igual a la longitud de esta cadena. ¿Para qué es este número? Contendrá el número (identificador) del hexágono al que queremos ir. Por defecto, es minúscula latina y números 0-9. La mayor parte del texto está codificado aquí, por lo que será un gran número: varios miles de bits (dependiendo del número de caracteres en la página), pero se procesará carácter por carácter.
  • alfabeto : la cadena, los caracteres que queremos ver en la biblioteca. Estará lleno de ellos. Para que todo funcione correctamente, la cantidad de caracteres en el alfabeto debe ser igual a la cantidad de caracteres en la cadena con posibles dígitos del número que identifica el hexágono.
  • pared - número, número máximo de pared, por defecto 5
  • estante - número, número máximo de estante , predeterminado 7
  • volumen - número, número máximo de libros, por defecto 31
  • página - número, número máximo de página, predeterminado 421

Como puede ver, esto es un poco como la verdadera biblioteca babilónica de Luis Borges. Pero he dicho más de una vez que crearemos bibliotecas "universales" que pueden ser la forma en que queremos verlas (por lo tanto, el número hexadecimal se puede interpretar de alguna manera diferente, por ejemplo, solo el identificador de algún lugar donde se almacena el deseado) información). La biblioteca babilónica es solo una de ellas. Pero todos tienen mucho en común: un algoritmo es responsable de su rendimiento, que ahora se discutirá.

Búsqueda de páginas y algoritmos de visualización


Cuando vamos a alguna dirección, vemos el contenido de la página. Si volvemos a la misma dirección nuevamente, el contenido debe ser exactamente el mismo. Esta propiedad de las bibliotecas proporciona un algoritmo para generar números pseudoaleatorios, el método congruente lineal . Cuando necesitemos seleccionar un carácter para generar la dirección o, por el contrario, el contenido de la página, nos ayudará, y el grano utilizará números de página, estantes, etc. La configuración de mi PRNG: m = 2 ^ 32 (4294967296), a = 22695477, c = 1. También me gustaría agregar que en nuestra implementación solo queda el principio de generación de números del método congruente lineal, el resto cambia. Seguimos adelante con la lista de programas:

Código
 module.exports = ({ lengthOfPage = 4819, lengthOfTitle = 31, digs = '0123456789abcdefghijklmnopqrstuvwxyz', alphabet = ', .', wall = 5, shelf = 7, volume = 31, page = 421, } = {}) => { let seed = 13; //   const rnd = (min = 1, max = 0) => { //   //    min  max seed = (seed * 22695477 + 1) % 4294967296; //   //      return min + seed / 4294967296 * (max - min); //   //   }; const pad = (s, size) => s.padStart(size, `0`); //   //       let getHash = str => parseInt(sha512(str).slice(0, 7), 16); //  const mod = (a, b) => ((a % b) + b) % b; //    const digsIndexes = {}; //     //    digs const alphabetIndexes = {}; //     //    alphabet Array.from(digs).forEach((char, position) => { //    digs digsIndexes[char] = position; //     //   }); Array.from(alphabet).forEach((char, position) => { //    alphabet alphabetIndexes[char] = position; //     //   }); return { //    }; 


Como puede ver, el grano PRNG cambia después de cada recibo del número, y los resultados dependen directamente del llamado punto de referencia: el grano, después del cual los números nos interesarán. (generamos la dirección u obtenemos el contenido de la página)

La función getHash nos ayudará a generar un punto de referencia. Solo obtenemos un hash de algunos datos, tomamos 7 caracteres, traducimos a un sistema de números decimales y ¡listo!

La función mod se comporta igual que el operador%. Pero si el dividendo es un <0 (tales situaciones son posibles), la función mod devolverá un número positivo debido a la estructura especial, necesitamos que esto seleccione correctamente los caracteres de la cadena del alfabeto al recibir el contenido de la página en la dirección.

Y el último fragmento de código de postre es el objeto de biblioteca devuelto:

Código
 return { wall, shelf, volume, page, lengthOfPage, lengthOfTitle, search(searchStr) { let wall = `${(Math.random() * this.wall + 1 ^ 0)}`, shelf = `${(Math.random() * this.shelf + 1 ^ 0)}`, volume = pad(`${(Math.random()* this.volume + 1 ^ 0)}`, 2), page = pad(`${(Math.random()* this.page + 1 ^ 0)}`, 3), locHash = getHash(`${wall}${shelf}${volume}${page}`), hex = ``, depth = Math.random() * (this.lengthOfPage - searchStr.length) ^ 0; for (let i = 0; i < depth; i++){ searchStr = alphabet[Math.random() * alphabet.length ^ 0] + searchStr; } seed = locHash; for (let i = 0; i < searchStr.length; i++){ let index = alphabetIndexes[searchStr[i]] || -1, rand = rnd(0, alphabet.length), newIndex = mod(index + parseInt(rand), digs.length), newChar = digs[newIndex]; hex += newChar; } return `${hex}-${wall}-${shelf}-${+volume}-${+page}`; }, searchExactly(text) { const pos = Math.random() * (this.lengthOfPage - text.length) ^ 0; return this.search(`${` `.repeat(pos)}${text}${` `.repeat(this.lengthOfPage - (pos + text.length))}`); }, searchTitle(searchStr) { let wall = `${(Math.random() * this.wall + 1 ^ 0)}`, shelf = `${(Math.random() * this.shelf + 1 ^ 0)}`, volume = pad(`${(Math.random()* this.volume + 1 ^ 0)}`, 2), locHash = getHash(`${wall}${shelf}${volume}`), hex = ``; searchStr = searchStr.substr(0, this.lengthOfTitle); searchStr = searchStr.length == this.lengthOfTitle ? searchStr : `${searchStr}${` `.repeat(this.lengthOfTitle - searchStr.length)}`; seed = locHash; for (let i = 0; i < searchStr.length; i++){ let index = alphabetIndexes[searchStr[i]], rand = rnd(0, alphabet.length), newIndex = mod(index + parseInt(rand), digs.length), newChar = digs[newIndex]; hex += newChar; } return `${hex}-${wall}-${shelf}-${+volume}`; }, getPage(address) { let addressArray = address.split(`-`), hex = addressArray[0], locHash = getHash(`${addressArray[1]}${addressArray[2]}${pad(addressArray[3], 2)}${pad(addressArray[4], 3)}`), result = ``; seed = locHash; for (let i = 0; i < hex.length; i++) { let index = digsIndexes[hex[i]], rand = rnd(0, digs.length), newIndex = mod(index - parseInt(rand), alphabet.length), newChar = alphabet[newIndex]; result += newChar; } seed = getHash(result); while (result.length < this.lengthOfPage) { result += alphabet[parseInt(rnd(0, alphabet.length))]; } return result.substr(result.length - this.lengthOfPage); }, getTitle(address) { let addressArray = address.split(`-`), hex = addressArray[0], locHash = getHash(`${addressArray[1]}${addressArray[2]}${pad(addressArray[3], 2)}`), result = ``; seed = locHash; for (let i = 0; i < hex.length; i++) { let index = digsIndexes[hex[i]], rand = rnd(0, digs.length), newIndex = mod(index - parseInt(rand), alphabet.length), newChar = alphabet[newIndex]; result += newChar; } seed = getHash(result); while (result.length < this.lengthOfTitle) { result += alphabet[parseInt(rnd(0, alphabet.length))]; } return result.substr(result.length - this.lengthOfTitle); } }; 


Al principio, le escribimos las propiedades de la biblioteca que describí anteriormente. Puede cambiarlos incluso después de que se llame a la función principal (que, en principio, se puede llamar un constructor, pero mi código es débilmente similar a la implementación de la clase de la biblioteca, por lo que me limitaré a la palabra "main"). Quizás este comportamiento no sea del todo adecuado, sino flexible. Ahora repase cada método.

Método de búsqueda


 search(searchStr) { let wall = `${(Math.random() * this.wall + 1 ^ 0)}`, shelf = `${(Math.random() * this.shelf + 1 ^ 0)}`, volume = pad(`${(Math.random() * this.volume + 1 ^ 0)}`, 2), page = pad(`${(Math.random() * this.page + 1 ^ 0)}`, 3), locHash = getHash(`${wall}${shelf}${volume}${page}`), hex = ``, depth = Math.random() * (this.lengthOfPage - searchStr.length) ^ 0; for (let i = 0; i < depth; i++){ searchStr = alphabet[Math.random() * alphabet.length ^ 0] + searchStr; } seed = locHash; for (let i = 0; i < searchStr.length; i++){ let index = alphabetIndexes[searchStr[i]] || -1, rand = rnd(0, alphabet.length), newIndex = mod(index + parseInt(rand), digs.length), newChar = digs[newIndex]; hex += newChar; } return `${hex}-${wall}-${shelf}-${+volume}-${+page}`; } 

Devuelve la dirección de la cadena searchStr en la biblioteca. Para hacer esto, seleccione al azar pared, estante, volumen, página . volumen y página también rellenados con ceros a la longitud deseada. A continuación, concatenelos en una cadena para pasar a la función getHash . El locHash resultante es el punto de partida, es decir. el grano

Para una mayor imprevisibilidad, complementamos la profundidad de searchStr con caracteres pseudoaleatorios del alfabeto, configuramos la semilla inicial en locHash . En esta etapa, no importa cómo complementamos la línea, por lo que puede usar el PRNG de JavaScript incorporado, esto no es crítico. Puede abandonarlo por completo para que los resultados que nos interesan estén siempre en la parte superior de la página.

Lo único que queda es generar el identificador del hexágono. Para cada carácter de la cadena searchStr , ejecutamos el algoritmo:

  1. Obtenga el número del carácter de índice en el alfabeto del objeto alphabetIndexes . Si no es así, devuelve -1, pero si esto sucede, definitivamente estás haciendo algo mal.
  2. Genere un rand de número pseudoaleatorio usando nuestro PRNG, en el rango de 0 a la longitud del alfabeto.
  3. Calcule el nuevo índice, que se calcula como la suma del número del índice del símbolo y el número rand pseudoaleatorio, dividido en módulo la longitud de las excavaciones .
  4. Por lo tanto, obtuvimos el dígito del identificador del hexágono: newChar (tomándolo de las excavaciones ).
  5. Agregue newChar al identificador hexadecimal hexadecimal

Al finalizar la generación hexadecimal , devolvemos la dirección completa del lugar en el que está contenida la línea deseada. Los componentes de la dirección están separados por un guión.

Método SearchExactly


 searchExactly(text) { const pos = Math.random() * (this.lengthOfPage - text.length) ^ 0; return this.search(`${` `.repeat(pos)}${text}${` `.repeat(this.lengthOfPage - (pos + text.length))}`); } 

Este método hace lo mismo que el método de búsqueda , pero llena todo el espacio libre (hace que la cadena de búsqueda searchStr con una longitud de caracteres lengthOfPage ). Al ver una página de este tipo, parecerá que no hay nada más que su texto.

Método SearchTitle


 searchTitle(searchStr) { let wall = `${(Math.random() * this.wall + 1 ^ 0)}`, shelf = `${(Math.random() * this.shelf + 1 ^ 0)}`, volume = pad(`${(Math.random()* this.volume + 1 ^ 0)}`, 2), locHash = getHash(`${wall}${shelf}${volume}`), hex = ``; searchStr = searchStr.substr(0, this.lengthOfTitle); searchStr = searchStr.length == this.lengthOfTitle ? searchStr : `${searchStr}${` `.repeat(this.lengthOfTitle - searchStr.length)}`; seed = locHash; for (let i = 0; i < searchStr.length; i++){ let index = alphabetIndexes[searchStr[i]], rand = rnd(0, alphabet.length), newIndex = mod(index + parseInt(rand), digs.length), newChar = digs[newIndex]; hex += newChar; } return `${hex}-${wall}-${shelf}-${+volume}`; } 

El método searchTitle devuelve la dirección de un libro llamado searchStr . En el interior, es muy similar a la búsqueda . La diferencia es que al calcular locHash no usamos la página para vincular su nombre al libro. No debe depender de la página. searchStr se trunca a lengthOfTitle y se rellena con espacios si es necesario. Del mismo modo, se genera el identificador del hexágono y se devuelve la dirección recibida. Tenga en cuenta que no hay ninguna página, como cuando buscaba la dirección exacta del texto arbitrario. Entonces, si desea averiguar qué hay en el libro con el nombre que acuñó, decida la página a la que desea ir.

Método GetPage


 getPage(address) { let addressArray = address.split(`-`), hex = addressArray[0], locHash = getHash(`${addressArray[1]}${addressArray[2]}${pad(addressArray[3], 2)}${pad(addressArray[4], 3)}`), result = ``; seed = locHash; for (let i = 0; i < hex.length; i++) { let index = digsIndexes[hex[i]], rand = rnd(0, digs.length), newIndex = mod(index - parseInt(rand), alphabet.length), newChar = alphabet[newIndex]; result += newChar; } seed = getHash(result); while (result.length < this.lengthOfPage) { result += alphabet[parseInt(rnd(0, alphabet.length))]; } return result.substr(result.length - this.lengthOfPage); } 

Lo contrario del método de búsqueda . Su tarea es devolver el contenido de la página a la dirección especificada. Para hacer esto, convertimos la dirección a una matriz usando el separador "-". Ahora tenemos una serie de componentes de dirección: identificador hexagonal, pared, estante, libro, página. Calculamos locHash de la misma manera que lo hicimos en el método de búsqueda . Obtenemos el mismo número que cuando generamos la dirección. Esto significa que el PRNG producirá los mismos números, es este comportamiento el que garantiza la reversibilidad de nuestras transformaciones sobre el texto fuente. Para calcularlo, realizamos el algoritmo en cada carácter (de hecho, esto es un dígito) del identificador del hexágono:

  1. Calculamos el índice en las excavaciones de cadenas. Tómelo de digsIndexes .
  2. Usando el PRNG, generamos un rand de número pseudoaleatorio en el rango de 0 a la base del sistema de números de un número grande, igual a la longitud de la cadena que contiene los dígitos de este hermoso número. Todo es obvio.
  3. Calculamos la posición del símbolo del texto fuente newIndex como la diferencia entre el índice y el rand , dividido en módulo a lo largo del alfabeto. Es posible que la diferencia sea negativa, entonces el módulo de división habitual dará un índice negativo, que no nos conviene, por lo que utilizamos una versión modificada de la división del módulo. (puede probar la opción de tomar el valor absoluto de la fórmula anterior, esto también resuelve el problema de los números negativos, pero en la práctica esto aún no se ha probado)
  4. El carácter del texto de la página es newChar , obtenemos el índice del alfabeto.
  5. Agregue un carácter de texto al resultado.

El resultado obtenido en esta etapa no siempre llenará toda la página, por lo que calcularemos el nuevo grano a partir del resultado actual y llenaremos el espacio libre con caracteres del alfabeto. El PRNG nos ayuda a elegir un símbolo.

Esto completa el cálculo del contenido de la página, lo devolvemos, sin olvidar recortarlo a la longitud máxima. Quizás el identificador del hexágono era indecentemente grande en la dirección de entrada.

Método GetTitle


 getTitle(address) { let addressArray = address.split(`-`), hex = addressArray[0], locHash = getHash(`${addressArray[1]}${addressArray[2]}${pad(addressArray[3], 2)}`), result = ``; seed = locHash; for (let i = 0; i < hex.length; i++) { let index = digsIndexes[hex[i]], rand = rnd(0, digs.length), newIndex = mod(index - parseInt(rand), alphabet.length), newChar = alphabet[newIndex]; result += newChar; } seed = getHash(result); while (result.length < this.lengthOfTitle) { result += alphabet[parseInt(rnd(0, alphabet.length))]; } return result.substr(result.length - this.lengthOfTitle); } 

Bueno, la historia es la misma. Imagine leer la descripción del método anterior, solo cuando el cálculo de los granos de PRNG no tiene en cuenta el número de página, y agregue y recorte el resultado a la longitud máxima del título del libro - lengthOfTitle .

Probar el módulo para crear bibliotecas


Después de examinar el principio de funcionamiento de cualquier biblioteca de estilo babilónico, es hora de probarlo todo en la práctica. Usaré la configuración lo más cerca posible de la creada por Louis Borges. Buscaremos una frase simple "habr.com":

 const libraryofbabel = require(`libraryofbabel`)({ lengthOfPage: 3200, alphabet: `abcdefghijklmnopqrstuvwxyz, .`, //, , ,  digs: `0123456789abcdefghijklmnopqrs`, // - 29-  wall: 4, shelf: 5, volume: 32, page: 410 //   }); //  console.log(libraryofbabel.search(`habr.com`)); 

Corre, el resultado:

imagen

Por el momento, no nos da nada. ¡Pero descubramos qué se esconde detrás de esta dirección! El código será así:

 const libraryofbabel = require(`libraryofbabel`)({ lengthOfPage: 3200, alphabet: `abcdefghijklmnopqrstuvwxyz, .`, //, , ,  digs: `0123456789abcdefghijklmnopqrs`, // - 29-  wall: 4, shelf: 5, volume: 32, page: 410 //   }); const text = `habr.com`; //  const adress = libraryofbabel.search(text); //    const clc = require(`cli-color`); //      console.log(libraryofbabel.getPage(adress).replace(text, clc.green(text))); 

Resultado:

imagen

¡Encontramos lo que estábamos buscando en un número infinito de páginas sin sentido (apuesto)!

Pero esto está lejos de ser el único lugar donde se encuentra esta frase. La próxima vez que se inicie el programa, se generará otra dirección. Si lo desea, puede guardar uno y trabajar con él. Lo principal es que el contenido de las páginas nunca cambia. Veamos el título del libro en el que se encuentra nuestra frase. El código será el siguiente:

 const libraryofbabel = require(`libraryofbabel`)({ lengthOfPage: 3200, alphabet: `abcdefghijklmnopqrstuvwxyz, .`, //, , ,  digs: `0123456789abcdefghijklmnopqrs`, // - 29-  wall: 4, shelf: 5, volume: 32, page: 410 //   }); const text = `habr.com`; //  const adress = libraryofbabel.search(text); //    const clc = require(`cli-color`); //      console.log(libraryofbabel.getPage(adress).replace(text, clc.green(text))); console.log(`\n : ${clc.green(libraryofbabel.getTitle(adress))}`); 

El título del libro es algo como esto:

imagen

Honestamente, no se ve muy atractivo. Entonces busquemos un libro con nuestra frase en el título:

 const libraryofbabel = require(`libraryofbabel`)({ lengthOfPage: 3200, alphabet: `abcdefghijklmnopqrstuvwxyz, .`, //, , ,  digs: `0123456789abcdefghijklmnopqrs`, // - 29-  wall: 4, shelf: 5, volume: 32, page: 410 //   }); const text = `habr.com`; //  const adress = libraryofbabel.searchTitle(text); //    const newAdress = `${adress}-${1}`; //    console.log(libraryofbabel.getPage(newAdress)); //     console.log(libraryofbabel.getTitle(newAdress)); //  ,        :) 

imagen

Ahora entiendes cómo usar esta biblioteca. Permítanme demostrar la posibilidad de crear una biblioteca completamente diferente. Ahora estará lleno de unos y ceros, cada página tendrá 100 caracteres, la dirección será un número hexadecimal. No olvide observar la condición para la igualdad de las longitudes del alfabeto y la cadena de dígitos de nuestro gran número. Buscaremos, por ejemplo, "10101100101010111001000000". Buscamos:

 const libraryofbabel = require(`libraryofbabel`)({ lengthOfPage: 100, alphabet: `1010101010101010`, // 1  0,     digs: `0123456789abcdef`, // - 16-  wall: 4, shelf: 5, volume: 32, page: 410 //   }); const text = `10101100101010111001000000`; //  const adress = libraryofbabel.search(text); //    console.log(`\n${adress}\n`); //    const clc = require(`cli-color`); //      console.log(libraryofbabel.getPage(adress).replace(text, clc.green(text))); console.log(`\n : ${clc.green(libraryofbabel.getTitle(adress))}`); 

imagen

Echemos un vistazo para encontrar una coincidencia completa. Para hacer esto, regresemos al ejemplo anterior y en el código reemplace libraryofbabel.search con libraryofbabel.searchExactly :

 const libraryofbabel = require(`libraryofbabel`)({ lengthOfPage: 3200, alphabet: `abcdefghijklmnopqrstuvwxyz, .`, //, , ,  digs: `0123456789abcdefghijklmnopqrs`, // - 29-  wall: 4, shelf: 5, volume: 32, page: 410 //   }); const text = `habr.com`; //  const adress = libraryofbabel.searchExactly(text); //    const clc = require(`cli-color`); //      console.log(libraryofbabel.getPage(adress).replace(text, clc.green(text))); console.log(`\n : ${clc.green(libraryofbabel.getTitle(adress))}`); 

imagen

Conclusión


Después de leer la descripción del algoritmo de operación de la biblioteca, probablemente ya adivinó que esto era una especie de engaño.Cuando busca algo significativo en la biblioteca, simplemente se codifica en una forma diferente y se muestra en una forma diferente. Pero está tan bien servido que comienzas a creer en estas interminables filas de hexágonos. De hecho, esto no es más que una abstracción matemática. Pero el hecho de que en esta biblioteca pueda encontrar absolutamente cualquier cosa, cualquier cosa, es cierto. La verdad es que si genera secuencias aleatorias de caracteres, tarde o temprano puede obtener absolutamente cualquier texto. Para una mejor comprensión de este tema, puede estudiar el teorema del mono sin fin .

También puede encontrar otras opciones para implementar bibliotecas: use cualquier algoritmo de cifrado, donde el texto cifrado será la dirección en su biblioteca completa. Descifrado: obtener el contenido de la página. O tal vez intentebase64 , m?

Un posible uso de la biblioteca es almacenar contraseñas en algunos de sus lugares. Cree la configuración que necesita, descubra dónde están sus contraseñas en la biblioteca (sí, ya existen. ¿Y pensó que fue usted quien las inventó?), Guarde la dirección. Y ahora, cuando necesite encontrar algún tipo de contraseña, búsquela en la biblioteca. Pero este enfoque es peligroso, porque un atacante puede encontrar la configuración de la biblioteca y simplemente usar su dirección. Pero si no sabe el significado de lo que encontró, es poco probable que sus datos lleguen a él. ¿Y es realmente un método de almacenamiento de contraseña tan convencional? No, entonces tiene un lugar para estar.

Esta idea puede usarse para crear una variedad de "bibliotecas". ¡Puede iterar no solo sobre caracteres, sino también sobre palabras completas o incluso sonidos! Imagine un lugar donde pueda escuchar absolutamente cualquier sonido disponible para la percepción humana, o encontrar algún tipo de canción. En el futuro definitivamente intentaré implementar esto.

La versión web en ruso está disponible aquí , se implementa en mi servidor virtual. No conozco todas las búsquedas agradables del significado de la vida en la biblioteca de Babilonia, o lo que quieres crear. Adios :)

Source: https://habr.com/ru/post/es433336/


All Articles