+ This text will be slowly rewritten by similar words.
+ You can choose the degree of similarity for its rewriting by typing a number between 1 and 10 :
+ 5
+ possible words with similarity degree of 5 : ['da', 'otros', 'salud', 'entre', 'así:', 'golpea', 'mira', 'del',
+ 'está', 'lo', 'valda.', 'tregua', 'unas', 'el', 'las', 'tenía', 'pastillas', 'con', 'verlo', 'hojas', 'gran',
+ 'este', 'leña']
+ word to be replaced in text: catala
+ replacement word: unas
+
+
+ element of original word in text to be compared: c
+ element of replacement word to be compared: u
+ in between word where selected letters of original word replace selected letters of replacement word: cnas
+ difference between c and u : 0
+
+ c → u
+ [c → u]nas
+ c <> u 1
+
+ element of original word in text to be compared: c
+ element of replacement word to be compared: un
+ in between word where selected letters of original word replace selected letters of replacement word: cas
+ difference between c and un : 1
+
+
+ element of original word in text to be compared: c
+ element of replacement word to be compared: una
+ in between word where selected letters of original word replace selected letters of replacement word: cs
+ difference between c and una : 2
+
+
+ element of original word in text to be compared: c
+ element of replacement word to be compared: unas
+ in between word where selected letters of original word replace selected letters of replacement word: c
+ difference between c and unas : 3
+
+
+ element of original word in text to be compared: ca
+ element of replacement word to be compared: u
+ in between word where selected letters of original word replace selected letters of replacement word: canas
+ difference between ca and u : 1
+
+
+ element of original word in text to be compared: ca
+ element of replacement word to be compared: un
+ in between word where selected letters of original word replace selected letters of replacement word: caas
+ difference between ca and un : 1
+
+
+ element of original word in text to be compared: ca
+ element of replacement word to be compared: una
+ in between word where selected letters of original word replace selected letters of replacement word: cas
+ difference between ca and una : 2
+
+
+ element of original word in text to be compared: ca
+ element of replacement word to be compared: unas
+ in between word where selected letters of original word replace selected letters of replacement word: ca
+ difference between ca and unas : 3
+
+
+ element of original word in text to be compared: cat
+ element of replacement word to be compared: u
+ in between word where selected letters of original word replace selected letters of replacement word: catnas
+ difference between cat and u : 2
+
+
+ element of original word in text to be compared: cat
+ element of replacement word to be compared: un
+ in between word where selected letters of original word replace selected letters of replacement word: catas
+ difference between cat and un : 2
+
+
+ element of original word in text to be compared: cat
+ element of replacement word to be compared: una
+ in between word where selected letters of original word replace selected letters of replacement word: cats
+ difference between cat and una : 2
+
+
+ element of original word in text to be compared: cat
+ element of replacement word to be compared: unas
+ in between word where selected letters of original word replace selected letters of replacement word: cat
+ difference between cat and unas : 2
+
+
+ element of original word in text to be compared: cata
+ element of replacement word to be compared: u
+ in between word where selected letters of original word replace selected letters of replacement word: catanas
+ difference between cata and u : 3
+
+
+ element of original word in text to be compared: cata
+ element of replacement word to be compared: un
+ in between word where selected letters of original word replace selected letters of replacement word: cataas
+ difference between cata and un : 3
+
+
+ element of original word in text to be compared: cata
+ element of replacement word to be compared: una
+ in between word where selected letters of original word replace selected letters of replacement word: catas
+ difference between cata and una : 3
+
+
+ element of original word in text to be compared: cata
+ element of replacement word to be compared: unas
+ in between word where selected letters of original word replace selected letters of replacement word: cata
+ difference between cata and unas : 3
+
+
+ element of original word in text to be compared: catal
+ element of replacement word to be compared: u
+ in between word where selected letters of original word replace selected letters of replacement word: catalnas
+ difference between catal and u : 4
+
+
+ element of original word in text to be compared: catal
+ element of replacement word to be compared: un
+ in between word where selected letters of original word replace selected letters of replacement word: catalas
+ difference between catal and un : 4
+
+
+ element of original word in text to be compared: catal
+ element of replacement word to be compared: una
+ in between word where selected letters of original word replace selected letters of replacement word: catals
+ difference between catal and una : 4
+
+
+ element of original word in text to be compared: catal
+ element of replacement word to be compared: unas
+ in between word where selected letters of original word replace selected letters of replacement word: catal
+ difference between catal and unas : 3
+
+
+ element of original word in text to be compared: catala
+ element of replacement word to be compared: u
+ in between word where selected letters of original word replace selected letters of replacement word: catalanas
+ difference between catala and u : 5
+
+
+ element of original word in text to be compared: catala
+ element of replacement word to be compared: un
+ in between word where selected letters of original word replace selected letters of replacement word: catalaas
+ difference between catala and un : 5
+
+
+ element of original word in text to be compared: catala
+ element of replacement word to be compared: una
+ in between word where selected letters of original word replace selected letters of replacement word: catalas
+ difference between catala and una : 5
+
+
+ element of original word in text to be compared: catala
+ element of replacement word to be compared: unas
+ in between word where selected letters of original word replace selected letters of replacement word: catala
+ difference between catala and unas : 4
+
+ Un fama anda por el bosque y aunque no necesita leña mira codiciosamente los árboles. Los árboles tienen un miedo
+ terrible porque conocen las costumbres de los famas y temen lo peor. En medio de todos está un eucalipto hermoso, y
+ el fama al verlo da un grito de alegría y baila tregua y baila <> en torno del perturbado eucalipto, diciendo
+ así:
+
+
+ – Hojas antisépticas, invierno con salud, gran higiene.
+
+
+ Saca un hacha y golpea al eucalipto en el estómago, sin importársele nada. El eucalipto gime, herido de muerte, y
+ los otros árboles oyen que dice entre suspiros:
+
+
+ – Pensar que este imbécil no tenía más que comprarse unas pastillas Valda.
+
+
+
+
\ No newline at end of file
diff --git a/html/makepdf.py b/html/makepdf.py
new file mode 100644
index 0000000..04074fd
--- /dev/null
+++ b/html/makepdf.py
@@ -0,0 +1,4 @@
+from weasyprint import HTML
+
+HTML(filename='content.html')\
+ .write_pdf('weasyprint-library.pdf')
diff --git a/la_distancia_de_levenshtein_lee_a_cortazar.py b/la_distancia_de_levenshtein_lee_a_cortazar.py
new file mode 100644
index 0000000..bd6fc49
--- /dev/null
+++ b/la_distancia_de_levenshtein_lee_a_cortazar.py
@@ -0,0 +1,315 @@
+#!/usr/bin/env/ python
+
+# This script unfolds the Levenhstein Distance algorithm,
+# often used in spellcheckers and to detect similarity between texts.
+# The algorithm reads a fragment on a eucalyptus tree from
+# Julio Cortazar's 'Historias de Cronopios y Famas', Alfaguara, 2012.
+
+# Copyright (C) 2021, Anais Berck
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details: .
+
+# Python libraries
+import random
+import math
+import random
+import textwrap
+import Levenshtein
+import sys
+
+# Functions
+
+# Open & prepare textfile for machinal reading
+def openfile(txt):
+ all_text = []
+ with open(txt, 'r') as source:
+ # Read the text
+ text = source.read()
+ # Remove punctuation
+ characters = ['\n', '-', ':', '.', ',']
+ for c in characters:
+ if c in text:
+ clean_text = text.replace(c,' ')
+ # Transform fragment in a list of words
+ words = clean_text.split()
+ # Recolt all unique words of the fragment in a set of words
+ for word in words:
+ word = word.lower()
+ word = word.strip()
+ all_text.append(word)
+ return all_text
+
+# Levenhstein Distance
+def levenshtein(a, b):
+ if not a: return len(b)
+ if not b: return len(a)
+ return min(levenshtein(a[1:], b[1:])+(a[0] != b[0]),
+ levenshtein(a[1:], b)+1,
+ levenshtein(a, b[1:])+1)
+
+# Create map
+def space_available (grid, start, end, line):
+ other_words = grid[line]
+
+ for other_start, other_end, _ in other_words:
+ if start < other_end and end > other_start:
+ return False
+ return True
+
+# Create frame
+def formatTable(words, cellWidth, cellHeight, padding=1, cells=6):
+ def makeRow (height):
+ return [''] * cellHeight
+
+ def makeLine (width, text = '', fillChar=' ', padding=1):
+ text = (padding * fillChar) + text
+ return text.center(width - padding, ' ') + (padding * fillChar)
+
+ out = ""
+
+ row = makeRow(cellHeight)
+
+ cell = 0
+
+ for word in words:
+ wrapped = textwrap.wrap(word, width=cellWidth - (2 * padding))
+ lines = padding * [makeLine(cellWidth, padding=padding)]
+
+ for line in wrapped:
+ lines.append(makeLine(cellWidth, text=line))
+
+ for _ in range(cellHeight - len(lines)):
+ lines.append(makeLine(cellWidth, padding=padding))
+
+ cell += 1
+
+ for (i, line) in enumerate(lines):
+ row[i] += line
+
+ if cell == cells:
+ out += '\n'.join(row)
+ row = makeRow(cellHeight)
+ cell = 0
+
+ if cell > 0:
+ out += '\n'.join(row)
+ row = makeRow(cellHeight)
+
+ return out
+
+# print statements for interaction with reader
+def pick_new_main_tree_terminal(fragment, all_simple, file_out=sys.stdout):
+ print(fragment, file=file_out)
+ ## ask input reader
+ print("\nPara que La Distancia de Levenshtein pueda leer el texto y producir un libro único, necesitas cambiar una palabra.", file=file_out)
+ print("\nPuedes elegir otra especie de árbol para el eucalipto, el árbol principal del fragmento. La Distancia de Levenshtein calculará entonces qué especie se encuentra en su cercanía y se reemplazará en el fragmento la palabra más genérica 'árboles' por esta nueva especie.", file=file_out)
+ print("\nPor favor, elige el árbol principal de la lista siguiente:", file=file_out)
+ print(', '.join(all_simple), file=file_out)
+ print("\nQuiero reemplazar el eucalipto por:", file=file_out)
+ new_main_tree = input()
+ while new_main_tree not in all_simple:
+ print("Tal vez escribiste mal la especie, por favor intente de nuevo.", file=file_out)
+ new_main_tree = input()
+ return new_main_tree
+
+# Levenshtein Distance between new main tree and other tree species
+def calculate_distances (center_tree, other_trees):
+ # Declare dictionary object
+ distances = {}
+ # For every species in the list, compare the main tree to the selected species and count the similarity between both
+ for tree in other_trees:
+ # using the Levenhstein Distance algorithm
+ # count = levenshtein(new_main_tree,tree)
+ count = Levenshtein.distance(center_tree, tree)
+ # save each compared species and its similarity count the dictionary
+ distances[tree] = count
+
+ return distances
+
+
+def sort_distances (distances):
+ return sorted(distances.items(), key = lambda kv: kv[1])
+
+
+# Find the minimum distance between new main tree and near species
+def find_nearest_species(sorted_distances, trees):
+ # First entry in sorted_distances is the new_main_tree, distance 0
+ # pick the next value
+ minimum_distance = sorted_distances[1][1]
+ possible_trees = []
+
+ for tree in sorted_distances[1:]:
+ if tree[1] == minimum_distance:
+ possible_trees.append(tree)
+ else:
+ break
+
+ near_species = random.choice(possible_trees)[0]
+ nearest_species = trees[near_species]
+
+ return (near_species, nearest_species)
+
+# rewrite fragment Cortazar
+def generate_new_fragment(fragment, new_main_tree, nearest_species):
+ new_fragment = fragment.replace("eucalipto", new_main_tree)
+ new_fragment = new_fragment.replace("árboles", nearest_species)
+ new_fragment = new_fragment.replace("Un fama anda", "Un fama ignorante anda")
+
+ return new_fragment
+
+# generate in between species and show the process of the Levenhstein Distance algorithm
+def generate_in_between_species (new_main_tree, near_species, file_out=sys.stdout):
+ # Define length of main character tree and major species
+ length_main_character_tree = len(new_main_tree)
+ length_near_species = len(near_species)
+
+ # Declare a list of in between words showing the process
+ in_between_species = []
+ # Loop over every number until reaching the total lenght of the original word
+ for cell in range(length_main_character_tree):
+ #print('row number: ', element)
+ # Loop over every number until reaching the total lenght of the replacement word
+ for number in range(length_near_species):
+ #print('column number: ', number)
+ # select the number of letters +1 of the original word
+ part1 = new_main_tree[:cell+1]
+ print('La Distancia de Levenshtein observa una parte del',new_main_tree, ':', part1, file=file_out)
+ # select the number of letters +1 of the replacement word
+ part2 = near_species[:number+1]
+ print('Después observa una parte del', near_species, ':', part2, file=file_out)
+ # selected letters of the original words replace the selected letters of the replacement word
+ new_species = part1 + near_species[number+1:]
+ print('En su intento de comparación reemplaza la parte del', near_species, 'por la parte del', new_main_tree, 'y crea así una nueva especie intermediaria: el', new_species, file=file_out)
+ # add in between words to the list
+ in_between_species.append(new_species)
+ # calculate the similarity between in between words
+ print('Calcula las acciones necesarias para reemplazar', new_main_tree[:cell+1], 'por', near_species[:number+1], ': ', Levenshtein.distance(new_main_tree[:cell+1], near_species[:number+1]), '\n', file=file_out)
+ # print('\n', file=file_out)
+
+ ## Print all in between words
+ #print('in between species: ', in_between_species, file=file_out)
+
+ return in_between_species
+
+# Draw a map of all in between species and their distance to main tree
+def print_map(sorted_distances, show_distances=True, file_out=sys.stdout):
+ # As characters are less wide than high make them a bit wider
+ xscale = 2
+ # Height of the map
+ height = 70
+ # Width of the map
+ width = int(70 * xscale)
+ # Centerpoint of the map
+ middle = (int(30 * xscale), 35)
+
+ grid = [[] for x in range(height + 1)]
+
+ centerpoint = sorted_distances[0][0]
+ start = middle[0] - max(0, int(len(centerpoint) / 2))
+
+ grid[middle[1]].append((start, start + len(centerpoint), centerpoint))
+
+ for treename, distance in sorted_distances[1:]:
+ placed = False
+
+ treename = ' {}({}) '.format(treename, distance) if show_distances else ' {} '.format(treename)
+ angle = random.random() * math.pi * 2
+ step = 0
+ steps = 180
+ while (not placed) and step < steps:
+
+ x = int(math.floor(math.cos(angle) * (distance * 2.8)) * xscale + middle[0])
+ y = int(math.floor(math.sin(angle) * (distance * 2.8)) + middle[1])
+
+ start = x - max(0, int(len(treename) / 2))
+ end = start + len(treename)
+
+ if space_available(grid, start, end, y):
+ grid[y].append((start, end, treename))
+ placed = True
+
+ angle += (math.pi * 2 / steps)
+ step += 1
+
+ if not placed:
+ print('Could not place {}'.format(treename), file=file_out)
+ # print(angle, x, y)
+
+ for row in grid:
+ # Sort by first key of the tuples, start of the word
+ row = sorted(row, key=lambda r: r[0])
+
+ if len(row):
+ line = ''
+ for start, _, treename in row:
+ line += ((start) - len(line)) * ' ' + treename
+
+ print(line, file=file_out)
+
+# draw table with all new intermediary species
+def print_table(new_main_tree, near_species, in_between_species, file_out=sys.stdout):
+ ## 8. Print tabel
+ print('{} → {}'.format(new_main_tree, near_species), file=file_out)
+ print('', file=file_out)
+ print(formatTable(in_between_species, 20, 5, cells=len(near_species)), file=file_out)
+
+# Execute functions
+if __name__ == '__main__':
+ ## 1A. Open textfiles & turn textfiles in machine readable lists
+
+ # Cortazar
+ txt = 'eucalipto_cortazar.txt'
+ # Open textfile
+ all_text = openfile(txt)
+
+ # List of trees
+ txt1 = 'arboles_simple.txt'
+ txt2 = 'arboles_plural.txt'
+ all_simple = openfile(txt1)
+ all_plural = openfile(txt2)
+
+ ## 1B. Turn list of trees into dictionary of single/plural words
+ trees = dict(zip(all_simple, all_plural))
+
+ ## 2. HOMEPAGE print statements
+ ## print fragment Cortazar
+ with open(txt, 'r') as source:
+ fragment = source.read()
+
+ ## 2b. Ask user to pick a new main tree
+ new_main_tree = pick_new_main_tree_terminal(fragment, all_simple, sys.stdout)
+
+ ## 3. Count the similarity between the main tree and the other species in the forest
+ distances = calculate_distances(new_main_tree, all_simple)
+
+ ## 4. Sort the distances between the trees and the new main tree from the lowest to the highest counts
+ sorted_distances = sort_distances(distances)
+
+ # Find the nearest species
+ near_species, nearest_species = find_nearest_species(sorted_distances, trees)
+
+ # Print rewritten fragment
+ print("\n")
+ new_fragment = generate_new_fragment(fragment, new_main_tree, nearest_species)
+ print(new_fragment, file=sys.stdout)
+
+ ## 6. Compare the similarity between the main character tree and the main species in the forest,
+ in_between_species = generate_in_between_species(new_main_tree, near_species, file_out=sys.stdout)
+
+ # Show the sorted distances dictionary
+ # print('Sorted distances: ', sorted_distances, file=sys.stdout)
+ # print('\n', file=sys.stdout)
+
+ # generate_new_text(fragment, new_main_tree, all_simple, all_plural, trees, sys.stdout)
+ ## 7. Generate map of the woods
+ print_map(sorted_distances, file_out=sys.stdout)
+
+ ## 8. Generate intermediary species table
+ print_table(new_main_tree, near_species, in_between_species, sys.stdout)
diff --git a/paper_original_vladimir_levenhstein_1966.pdf b/paper_original_vladimir_levenhstein_1966.pdf
new file mode 100644
index 0000000..8ff727b
Binary files /dev/null and b/paper_original_vladimir_levenhstein_1966.pdf differ
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..e362073
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+WeasyPrint
+python-Levenshtein
+flask
\ No newline at end of file
diff --git a/scrape_html_page.py b/scrape_html_page.py
new file mode 100644
index 0000000..2ce84f2
--- /dev/null
+++ b/scrape_html_page.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env/ python
+# encoding=utf8
+
+from bs4 import BeautifulSoup
+import requests
+
+species = []
+name_species = ''
+
+url = "https://www.arbolapp.es/especies-nombre-cientifico/"
+
+# Getting the webpage, creating a Response object.
+response = requests.get(url)
+
+if response:
+ # Extracting the source code of the page.
+ data = response.text
+ soup = BeautifulSoup(data, 'lxml')
+ # find all elements inside a div element of class contenido
+ selector = 'div.contenido > h4'
+ # find elements that contain the data we want
+ found = soup.select(selector)
+ for element in found:
+ heading_data = element.text
+ print(heading_data.lower())
+ # print('soup:', soup)
+ # for link in soup.find_all("a"):
+ # url = link.get("href", "")
+ # print('url:', url)
+ # if "/wiki/" in url:
+ # name_species = url.replace("/wiki/", "")
+ # species.append(name_species)
+
+ # destination = "List_of_tree_genera.txt"
+ # with open(destination, 'w') as source:
+ # for specie in species:
+ # source.write(specie)
+ # source.write('\n')
+else:
+ pass
+
+# complete_links =["https://en.wikipedia.org/wiki/", "https://es.wikipedia.org/wiki/", "https://fr.wikipedia.org/wiki/", "https://nl.wikipedia.org/wiki/"]
+
+'''
+comments:
+Trees of Africa refer to all countries listed here: https://en.wikipedia.org/wiki/Ecoregions_of_Africa
+
+'''
\ No newline at end of file
diff --git a/static/fonts/OFL.txt b/static/fonts/OFL.txt
new file mode 100644
index 0000000..7229a80
--- /dev/null
+++ b/static/fonts/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2020 The XanhMono Project Authors (https://github.com/yellow-type-foundry/xanhmono).
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/static/fonts/XanhMono-Italic.ttf b/static/fonts/XanhMono-Italic.ttf
new file mode 100644
index 0000000..8247acf
Binary files /dev/null and b/static/fonts/XanhMono-Italic.ttf differ
diff --git a/static/fonts/XanhMono-Italic.woff b/static/fonts/XanhMono-Italic.woff
new file mode 100644
index 0000000..36b61c4
Binary files /dev/null and b/static/fonts/XanhMono-Italic.woff differ
diff --git a/static/fonts/XanhMono-Italic.woff2 b/static/fonts/XanhMono-Italic.woff2
new file mode 100644
index 0000000..4ebe2c6
Binary files /dev/null and b/static/fonts/XanhMono-Italic.woff2 differ
diff --git a/static/fonts/XanhMono-Regular.ttf b/static/fonts/XanhMono-Regular.ttf
new file mode 100644
index 0000000..b56a225
Binary files /dev/null and b/static/fonts/XanhMono-Regular.ttf differ
diff --git a/static/fonts/XanhMono-Regular.woff b/static/fonts/XanhMono-Regular.woff
new file mode 100644
index 0000000..28f8bc8
Binary files /dev/null and b/static/fonts/XanhMono-Regular.woff differ
diff --git a/static/fonts/XanhMono-Regular.woff2 b/static/fonts/XanhMono-Regular.woff2
new file mode 100644
index 0000000..f2a5c80
Binary files /dev/null and b/static/fonts/XanhMono-Regular.woff2 differ
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..7c3d405
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,359 @@
+
+
+
+
+
+
+
+ La Distancia de Levenshtein lee a Cortázar
+
+
+
+
Fama y eucalipto
+
+
+ Un fama anda por el bosque y aunque no necesita leña mira codiciosamente los árboles. Los árboles tienen un miedo terrible porque conocen las costumbres de los famas y temen lo peor. En medio de todos está un eucalipto hermoso, y el fama al verlo da un grito de alegría y baila tregua y baila catala en torno del perturbado eucalipto, diciendo así:
+
+
+ – Hojas antisépticas, invierno con salud, gran higiene.
+
+
+ Saca un hacha y golpea al eucalipto en el estómago, sin importársele nada. El eucalipto gime, herido de muerte, y los otros árboles oyen que dice entre suspiros:
+
+
+ – Pensar que este imbécil no tenía más que comprarse unas pastillas Valda.
+
+
+
+
+
+
A ti
+
+ Para que La Distancia de Levenshtein pueda leer el fragmento y producir un libro único, necesitas cambiar una palabra.
+
+
+ Puedes elegir otra especie de árbol para el eucalipto, el árbol principal del fragmento. La Distancia de Levenshtein calculará entonces qué especie se encuentra en su cercanía y se reemplazará en el fragmento la palabra más genérica 'árboles' por esta nueva especie.
+
+
+
+
+
+
+
La Distancia de Levenshtein lee a Cortázar
+
'La Distancia de Levenshtein lee a Cortázar' es el quinto capítulo de ÁGORA / CEMENTO / CÓDIGO, una exposición online comisariada por Lekutan, dentro del programa Komisario Berriak, proyecto apoyado por Tabakalera en Donostia / San Sebastián. Anaïs Berck presenta aquí una primera versión de un libro en la editorial 'Editorial Algoliteraria: crear alianzas con los árboles'. En esta editorial los autores son algoritmos y los libros presentan los resultados narrativos escritos desde su punto de vista.
El tiraje del libro es por definición infinito y cada copia será única.
+
La distancia de Levenshtein, distancia de edición o distancia entre palabras es un algoritmo que opera en los correctores ortográficos. Es el número mínimo de operaciones requeridas para transformar una palabra en otra. Una operación puede ser una inserción, eliminación o la sustitución de un carácter. El algoritmo fue una invención del científico ruso Vladimir Levenshtein en 1965.
+
+
+
+
Levenshtein Distance reads Cortázar
+
'Levenshtein Distance reads Cortázar' is the fifth chapter of ÁGORA / CEMENTO / CÓDIGO, an online exhibition curated by Lekutan, within the programme of Komisario Berriak supported by Tabakalera. Anaïs Berck presents herewith a first version of a first book of the publishing house 'Algoliterary Publishing: making kin with trees'. In this publishing house the authors are algorithms, presented with their contexts and codes; and the books present the narrative point of view of the algorithm.
+
The author of this book is the algorithm Levenhstein Distance, the subject is the eucalyptus tree in "Fama y eucalipto", an excerpt from Historias de Cronopios y de Famas by Julio Cortázar.
+
The printrun of the book is by definition infinite and each copy is unique.
+
Levenshtein distance, edit distance or word distance is an algorithm that operates in spell checkers. It is the minimum number of operations required to transform one word into another. An operation can be an insertion, deletion or substitution of a character. The algorithm was an invention of Russian scientist Vladimir Levenshtein in 1965.
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/print.html b/templates/print.html
new file mode 100644
index 0000000..435e12e
--- /dev/null
+++ b/templates/print.html
@@ -0,0 +1,402 @@
+
+
+
+
+
+ La Distancia de Levenshtein lee a Cortázar {{ edition_count }}
+
+
+
+
+
+
+{{ fragment_cover_map }}
+
+
+
+
+
+
+
La Distancia de Levenshtein lee a Cortázar
+
+ Generado el {{ date }} a las {{ time }}, N⁰ {{ edition_count}}
+
+
+
Índice
+
+
Introducción
+
Lectura de Cortázar
+
+
Fragmento original
+
Fragmento adaptado
+
Mapa del bosque
+
Matriz de nuevas especies intermediarias
+
Poesía repetitiva
+
+
+
Descripción general de La Distancia de Levenshtein
+
La Distancia de Levenshtein explicada de manera técnica
+
Código
+
Créditos
+
+
+
+
1. Introducción
+
La Distancia de Levenshtein lee a Cortázar es la primera versión del primer libro en la 'Editorial Algoliteraria: crear alianzas con los árboles'.
El libro es por definición infinito y cada copia es única.
+
Anaïs Berck es un seudónimo y representa una colaboración entre humanos, algoritmos y árboles. Anaïs Berck explora las especificidades de la inteligencia humana en compañía de las inteligencias artificiales y vegetales. En junio 2021, durante una residencia en Medialab Prado en Madrid, Anaïs Berck desarrollará un prototipo de la Editorial Algoliteraria, en la que los algoritmos son los autores de libros inusuales. La residencia fue concedida por el programa "Residencia Cultura Digital" iniciado por el Gobierno Flamenco.
los seres humanos An Mertens y Gijs de Heij. An ha publicado varios libros, como escritora de ficción y como artista e investigadora en Constant, una organización para el arte experimental y los medios de comunicación en Bruselas de la que es miembro desde 2008. Gijs es programador y diseñador, forma parte del colectivo de diseñadores, Open Source Publishing en Bruselas. Ambxs son miembrxs de Algolit, un grupo de experimentación artística en Bruselas alrededor de algoritmos y textos libres.
+
+
+
+
2. Lectura de Cortázar
+
+
2.1. Fragmento original
+
+
+ Un fama anda por el bosque y aunque no necesita leña mira codiciosamente los árboles. Los árboles tienen un miedo terrible porque conocen las costumbres de los famas y temen lo peor. En medio de todos está un eucalipto hermoso, y el fama al verlo da un grito de alegría y baila tregua y baila catala en torno del perturbado eucalipto, diciendo así:
+
+
+ – Hojas antisépticas, invierno con salud, gran higiene.
+
+
+ Saca un hacha y golpea al eucalipto en el estómago, sin importársele nada. El eucalipto gime, herido de muerte, y los otros árboles oyen que dice entre suspiros:
+
+
+ – Pensar que este imbécil no tenía más que comprarse unas pastillas Valda.
+
+
+
+
+
+
2.2. Fragmento adaptado
+
+
{{ new_fragment }}
+
+
+
2.3. Mapa del bosque
+
Las distancias entre el árbol principal que has elegido para tu fragmento y las zonas de otras especies de árboles en el bosque, según La Distancia de Levenshtein:
+
+
+
+
+
+{{ forest_map }}
+
+
+
2.4. Matriz de nuevas especies intermediarias
+
La Distancia de Levenshtein crea una matriz con las dos especies. En esta matriz calcula para cada celda la distancia entre los elementos distintos de las dos palabras.
+
En realidad la matriz se llena de números que representan las operaciones necesarias para cambiar un elemento al otro. Las posibles operaciones son insertar, borrar o sustituir una letra. En vez de los números, esta matriz se llena con las distintas especies intermediarias que el algoritmo crea insertando, borrando o sustituyendo letras.
+
+
+
+
+{{ table_of_intermediary_species }}
+
+
+
2.5. Poesía repetitiva
+
+
+
{{ repetitive_poetry }}
+
+
+
+
3. Descripción general de La Distancia de Levenshtein
+
La Distancia de Levenshtein es un algoritmo que mide la diferencia entre dos palabras o dos grupos de letras. También se denomina la 'distancia de edición'. La Distancia de Levenshtein entre dos palabras es el número mínimo de acciones necesarias para cambiar una palabra por otra. Las diferentes acciones posibles son la inserción, la supresión o la substitución de una sola letra. Por ejemplo, la Distancia de Levenshtein entre 'más' y 'mes' es 1, ya que se sustituye 'á' por 'e'.
+
El algoritmo recibió el nombre de su creador, Vladimir Levenshtein, un matemático y científico ruso de origen judío cuya principal área de investigación era la teoría de la información y los códigos de corrección de errores. Trabajó en el Instituto Kéldysh de Matemática Aplicada en Moscú. Falleció en el 2017 a la edad de 82 años. Lanzó el algoritmo en 1965 'para considerar el problema de construir códigos óptimos capaces de corregir supresiones, inserciones e inversiones'.
+
La Distancia de Levenshtein opera en softwares como los correctores ortográficos y por consecuencia en programas de traducción asistida por computadora. También se puede encontrar la Distancia de Levenshtein en buscadores de información donde detecta las palabras más similares a la palabra entrada erróneamente.
+
Su actividad se extiende a campos menos evidentes como la detección de plagiarismo, el análisis de ADN, el reconocimiento automático de voz, el reconocimiento óptico de caracteres en el análisis de textos escaneados (OCR), el reconocimiento de la escritura a mano, la detección de hoax emails o la asistencia de venta y compras en el mercado de acciones.
+
A veces la Distancia de Levenshtein llega a descubrimientos sorprendentes. Así en 1995, Kessler aplicó el algoritmo a la comparación de dialectos irlandeses. Demostró que era un método exitoso para medir las distancias fonéticas entre los dialectos. A partir de las distancias lingüísticas entre variedades dialectales, se pueden encontrar áreas dialectales. Más innovadora era la posibilidad de dibujar mapas dialectales que reflejan el hecho de que las áreas dialectales deben considerarse como continuas y no como áreas separadas por fronteras nítidas.
S. Dutta Chowdhury; U. Bhattacharya; S.K. Parui, Online Handwriting Recognition Using Levenshtein Distance Metric, in 12th International Conference on Document Analysis and Recognition, 2013, USA.
+
Yoke Yie Chen, Suet-Peng Yong, and Adzlan Ishak, Email Hoax Detection System Using Levenshtein Distance Method, in Journal of Computers, vol. 9, nr 2, February 2014.
4. La Distancia de Levenshtein explicada de manera técnica
+
Los seres humanos pueden reescribir una palabra y contar fácilmente el nombre de cambios que son necesarios para transformar una palabra en otra. Le invitamos a escribir la palabra máquina en una hoja, seguida por la palabra humanx en la línea siguiente. Sabiendo que sólo se puede insertar, borrar o sustituir una letra, ¿cuántas operaciones necesitaría hacer para reescribir la palabra máquina en humanx?
+
Para que tenga una idea del modo de acción del algoritmo Distancia de Levenshtein, le describimos aquí los diferentes pasos que realiza el algoritmo para transformar la palabra máquina en humanx.
+
Para la palabra máquina, analiza primero los posibles elementos. Son m, má, máq, máqu, máqui, máquin y máquina para un total de siete elementos. Para la palabra humanx, los elementos son h, hu, hum, huma, human y humanx para un total de seis elementos. Esto crea una matriz con 7 filas y 6 columnas. En esta matriz de distancia calculará para cada celda la distancia entre los elementos de las dos palabras.
+
Comienza con el primer elemento de la palabra máquina que es m, lo compara con los seis elementos de la palabra humanx. El primero será h. ¿Cuál es la distancia de Levenshtein entre m y h? Lo que tiene que hacer es sustituir el carácter m por h, entonces la distancia es 1.
+
Pasa al siguiente elemento de la palabra humanx que es hu. ¿Cuál es la distancia de Levenshtein entre m y hu? Como el elemento contiene un solo carácter y hu contiene más de un carácter, puede estar 100% segurx de que tiene que insertar un nuevo carácter. Para transformar m en hu, primero el carácter m es reemplazado por h, y luego añade u. Para transformar m en hu, la distancia es 2.
+
Ahora pasa al tercer elemento. ¿Cuál es la distancia entre m y hum? Hace lo mismo que arriba, pero tiene que añadir otro carácter, m, también. La distancia final entonces es 3.
+
Continúa hasta que haya calculado la distancia entre el primer elemento de la palabra máquina, o m, y los 6 elementos de la segunda palabra humanx. Las distancias son simplemente 1, 2, 3, 4 y 5; simplemente aumentan de 1.
+
Después de calcular las distancias entre el primer prefijo de la primera palabra y todos los prefijos de la segunda palabra, el proceso continúa calculando las distancias entre los prefijos restantes de la primera palabra y los prefijos de la segunda palabra.
+
Sigue el proceso con má. Lo compara con los seis elementos de la palabra humanx. El primero será h. ¿Cuál es la distancia de Levenshtein entre má y h? Lo que tiene que hacer es sustituir el carácter m por h y borrar el carácter á. Entonces la distancia es 2. Pasa al siguiente elemento de la palabra humanx que es hu. ¿Cuál es la distancia de Levenshtein entre má y hu? Sustituye el carácter m por h y la letra á por u. La distancia es 2.
+
Y así rellena la matriz.
+
En términos de código se podría hablar de un efecto optimizador en la matriz.
+
Se calcula el valor basado en las tres cifras más cercanas de la celda en la matriz que corresponde a los caracteres que se comparan: horizontal, vertical, diagonal.
+
Si las letras son iguales, se elige el valor mínimo de las tres.
+
Si las letras son distintas, se elige el valor mínimo de las tres y se añade 1.
+
El último valor de la serie de cuentas es el que representa la distancia mínima entre las 2 palabras.
+
En la matriz es el valor situado en la esquina inferior derecha.
+
Finalmente es asunto de trazar el camino más breve en las transformaciones de una palabra a la otra:
+
+
el camino diagonal tratando de caracteres diferentes y representa la substitución
+
el camino diagonal tratando de caracteres iguales no representa ningún cambio
+
el camino hacia la izquierda representa una inserción