Compare commits

..

No commits in common. "master" and "v0.1.1" have entirely different histories.

81 changed files with 930 additions and 18720 deletions

2
.gitattributes vendored
View file

@ -1,2 +0,0 @@
*.bf linguist-vendored
*.b linguist-vendored

View file

@ -1,17 +1,15 @@
# brainfuck
Brainfuck interpreters in different languages
Get the releases!
Rust: CLI binary, in the release tab
Typescript: [react website](https://nilstrieb.github.io/brainfuck/)
Finished:
- Rust
- Rust o1
- Java
- Interactive TypeScript
WIP:
- Rust o2
To-Do:
- Idris
- Haskell
- TypeScript
- (JavaScript)

View file

@ -10,7 +10,7 @@ public class Brainfuck {
public List<Character> minify(String program) {
List<Character> chars = List.of('>', '<', '+', '-', '.', ',', '[', ']');
return program.chars().parallel()
return program.chars()
.mapToObj(c -> (char) c)
.filter(chars::contains)
.collect(Collectors.toList());

2
bfi-rust/.gitignore vendored
View file

@ -1,3 +1,5 @@
/target
.idea
# brainfuck testing code, get your own
*.b
*.bf

2
bfi-rust/Cargo.lock generated
View file

@ -2,4 +2,4 @@
# It is not intended for manual editing.
[[package]]
name = "bfinterpreter"
version = "0.1.1"
version = "0.1.0"

View file

@ -1,6 +1,6 @@
[package]
name = "bfinterpreter"
version = "0.1.1"
version = "0.1.0"
authors = ["Nilstrieb <nilstrieb@gmail.com>"]
edition = "2018"
@ -8,8 +8,6 @@ edition = "2018"
[dependencies]
[profile.release]
debug = true
[profile.dev]
opt-level = 3

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 437 KiB

23
ibfi-ts/.gitignore vendored
View file

@ -1,23 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View file

@ -1,27 +0,0 @@
# Interactive Brainfuck Interpreter in React TS
This is an interactive interpreter for the brainfuck programming language.
It provides simple brainfuck execution, along with a view of the memory, the memory pointer, the current state of the
code and more.
It is great for debugging brainfuck programs, including a memory view, program view, the location of the pointers, the
ability to directly edit memory.
You can step manually through the program, or set the execution speed to whatever speed fits best.
This interpreter also has the ability to set breakpoints using the • symbol. This means you can let your code run fast and
stopping it at any point in your program to see what went wrong.
## Features
* brainfuck execution including IO
* memory view
* code state view
* manual stepping
* breakpoints
* error messages
* seeing ASCII characters in memory
* manual code input
* fast excecution mode (no debugging info)
### Future features
* none-blocking fast excecution mode
* better speed control
* (limited) backstepping

View file

@ -1,50 +0,0 @@
{
"name": "ibfi-ts",
"version": "0.1.0",
"homepage": "https://nilstrieb.github.io/brainfuck",
"private": false,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"node-sass": "^6.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"sass": "^1.35.1",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"deploy": "yarn build && gh-pages -d build"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"gh-pages": "^3.2.3"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Interactive Brainfuck Interpreter"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Brainfuck Interpreter</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View file

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View file

@ -1,128 +0,0 @@
$main-color: #282c34;
$main-color-brighter: #323942;
$light-color: ghostwhite;
$medium-color: #78787f;
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
.App-header {
background-color: $main-color;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: $light-color;
}
.App-link {
color: #61dafb;
}
.bf-input {
.code-input {
resize: none;
width: 80vw;
height: 400px;
font-size: 100px;
}
.code-options-wrapper > * {
margin: 10px;
}
}
.code-display-wrapper {
max-width: 80vw;
font-family: monospace;
span {
word-wrap: break-word;
}
}
.memory-display-table {
$border: 1px solid $light-color;
th, .cell {
border: $border;
}
th, td {
min-width: 60px;
text-align: center;
}
.array-set-value-field {
min-width: 50px;
max-width: 100px;
height: 40px;
color: $light-color;
font-size: 30px;
background-color: $main-color-brighter;
}
}
.run-button {
height: 50px;
width: 200px;
}
.bf-run {
margin: 20px;
.speed-control-wrapper > * {
margin: 10px;
}
.small-speed-button {
height: 40px;
width: 40px;
}
.program-input-area {
resize: none;
width: 80vw;
height: 50px;
font-size: 30px;
}
.info {
background-color: #579ca7;
}
}
.bf-output {
.output-area {
resize: none;
width: 80vw;
height: 200px;
font-size: 20px;
}
}
textarea {
background-color: $main-color-brighter;
color: $light-color;
}
button {
background-color: $medium-color;
font-size: 20px;
border: 1px solid $main-color;
&:hover {
cursor: pointer;
background-color: $light-color;
}
}

View file

@ -1,157 +0,0 @@
import {CodeOptions} from "../components/CodeInput";
type InHandler = (() => number);
type OutHandler = ((char: number) => void);
export default class Interpreter {
private readonly _array: Uint8Array;
private _pointer: number;
private readonly _code: string;
private _programCounter: number;
private readonly _inHandler: InHandler;
private readonly _outHandler: OutHandler;
private readonly _options: CodeOptions;
constructor(input: [string, CodeOptions], outHandler: OutHandler, inHandler: InHandler) {
const buf = new ArrayBuffer(32000);
this._array = new Uint8Array(buf);
this._pointer = 0;
this._options = input[1];
if (input[1].minify) {
this._code = this.minify(input[0])
} else {
this._code = input[0];
}
this._programCounter = 0;
this._inHandler = inHandler;
this._outHandler = outHandler;
}
public next() {
this.execute(this._code[this._programCounter++]);
}
public execute(char: string) {
switch (char) {
case '+':
this._array[this._pointer]++;
break;
case '-':
this._array[this._pointer]--;
break;
case '>':
this._pointer++;
break;
case '<':
if (this._pointer === 0) {
throw new Error("Cannot wrap left");
}
this._pointer--;
break;
case '.':
this._outHandler(this.value);
break;
case ',':
this.input();
break;
case '[':
this.loopForwards();
break;
case ']':
this.loopBackwards();
break;
case '•':
if (this._options.enableBreakpoints) {
throw new Error("Breakpoint reached");
}
break;
case undefined:
this._programCounter = this._code.length;
break;
default:
break;
}
}
private loopForwards() {
if (this.value === 0) {
let level = 0;
while (this.lastInstruction !== ']' || level > -1) {
this._programCounter++;
if (this._programCounter > this._code.length) {
throw new Error("Reached end of code while searching ']'");
}
if (this.lastInstruction === '[') level++;
else if (this.lastInstruction === ']') level--;
}
}
}
private loopBackwards() {
if (this.value !== 0) {
let level = 0;
while (this.lastInstruction !== '[' || level > -1) {
this._programCounter--;
if (this._programCounter < 0) {
throw new Error("Reached start of code while searching '['");
}
if (this.lastInstruction === '[') level--;
else if (this.lastInstruction === ']') level++;
}
}
}
private input() {
try {
this._array[this._pointer] = this._inHandler();
} catch {
this._programCounter--;
}
}
get reachedEnd(): boolean {
return this._programCounter === this._code.length;
}
get lastInstruction(): string {
return this._code[this._programCounter - 1];
}
get value(): number {
return this._array[this._pointer];
}
get array(): Uint8Array {
return this._array;
}
get pointer(): number {
return this._pointer;
}
get code(): string {
return this._code;
}
get programCounter(): number {
return this._programCounter;
}
private minify(code: string): string {
const CHARS = ['+', '-', '<', '>', '.', ',', '[', ']'];
if (this._options.enableBreakpoints) {
CHARS.push('•');
}
return code.split("")
.filter(c => CHARS.includes(c))
.join("");
}
}

View file

@ -1,41 +0,0 @@
import '../App.scss';
import CodeInput, {CodeOptions} from "./CodeInput";
import ProgramOutput from "./ProgramOutput";
import React, {useCallback, useState} from "react";
import Runner from "./Runner";
export const OptionContext = React.createContext<CodeOptions>({});
function App() {
const [out, setOut] = useState("");
const [input, setInput] = useState<[string, CodeOptions]>(["", {}]);
const [running, setRunning] = useState(false);
const outHandler = useCallback((char: number) => {
setOut(oldOut => oldOut + String.fromCharCode(char))
}, []);
const runHandler = (run: boolean) => {
setRunning(run);
if (!run) {
setOut("");
}
}
const inputHandler = (code: string, options: CodeOptions) => setInput([code, options]);
return (
<div className="App-header">
<OptionContext.Provider value={input[1]}>
{
!running && <CodeInput input={input} setInput={inputHandler}/>
}
<Runner running={running} setRunning={runHandler} code={input[0]} outHandler={outHandler}/>
{
running && <ProgramOutput text={out}/>
}
</OptionContext.Provider>
</div>
);
}
export default App;

View file

@ -1,22 +0,0 @@
import React from 'react';
interface CodeDisplayProps {
code: string,
index: number,
}
const CodeDisplay = ({code, index}: CodeDisplayProps) => {
const firstCodePart = code.substr(0, index);
const secondCodePart = code.substr(index + 1, code.length - index + 1);
return (
<div className="code-display-wrapper">
<code>{firstCodePart}</code>
<code style={{backgroundColor: "red"}}>{code[index] || " "}</code>
<code>{secondCodePart}</code>
</div>
);
};
export default CodeDisplay;

View file

@ -1,83 +0,0 @@
import React, {ChangeEvent, useState} from 'react';
import presets from "../presets.json";
export interface CodeOptions {
minify?: boolean,
directStart?: boolean,
startSuperSpeed?: boolean,
enableBreakpoints?: boolean
asciiView?: boolean
}
interface CodeInputProps {
setInput: ((code: string, options: CodeOptions) => void),
input: [string, CodeOptions]
}
const codeOptions: Array<[string, keyof CodeOptions]> = [
["Minify Code", "minify"],
["Start directly", "directStart"],
["Start in blocking mode", "startSuperSpeed"],
["Breakpoints (•)", "enableBreakpoints"],
["Show ASCII in memory", "asciiView"]
]
const CodeInput = ({input: [code, options], setInput}: CodeInputProps) => {
const [fontSize, setFontSize] = useState(40);
const setPreset = (name: keyof typeof presets) => () => {
setInput(presets[name], options);
}
const changeHandler = (name: keyof CodeOptions) => (event: ChangeEvent<HTMLInputElement>) => {
setInput(code, {...options, [name]: event.target.checked})
}
return (
<div className="bf-input">
<div className="code-options-wrapper">
<div>
<label htmlFor="bf-input-fontsize-range">Font Size</label>
<input type="range" id="bf-input-fontsize-range" onChange={v => setFontSize(+v.target.value)}/>
</div>
{codeOptions.map(([display, id]) =>
<CodeOption displayName={display} name={id} options={options} onChange={changeHandler}/>
)}
</div>
<textarea value={code} onChange={e => setInput(e.target.value, options)} style={{fontSize}}
className="code-input"
placeholder="Input your code here..."/>
<div>
<div>Presets</div>
<div>
<button onClick={setPreset("helloworld")}>Hello World</button>
<button onClick={setPreset("hanoi")}>Towers of Hanoi</button>
<button onClick={setPreset("quine")}>Quine</button>
<button onClick={setPreset("gameoflife")}>Game Of Life</button>
<button onClick={setPreset("benchmark")}>Benchmark</button>
<button onClick={setPreset("fizzbuzz")}>Fizzbuzz</button>
</div>
</div>
</div>
);
};
interface CodeOptionProps {
displayName: string,
name: keyof CodeOptions,
options: CodeOptions,
onChange: (name: keyof CodeOptions) => (event: ChangeEvent<HTMLInputElement>) => void,
}
const CodeOption = ({displayName, name, options, onChange}: CodeOptionProps) => (
<span>
<input type="checkbox" checked={options[name]} id={`input-options-${name}`}
onChange={onChange(name)}/>
<label htmlFor={`input-options-${name}`}>{displayName}</label>
</span>
);
export default CodeInput;

View file

@ -1,15 +0,0 @@
import React from 'react';
interface ProgramOutputProps {
text: string
}
const ProgramOutput = ({text}: ProgramOutputProps) => {
return (
<div className="bf-output">
<textarea readOnly className="output-area" value={text}/>
</div>
);
};
export default ProgramOutput;

View file

@ -1,118 +0,0 @@
import React, {useContext, useRef, useState} from 'react';
import Interpreter from "../brainfuck/Interpreter";
import {OptionContext} from "./App";
const MAX_TABLE_COLUMNS = 20;
interface RunDisplayProps {
interpreter: Interpreter,
}
const RunDisplay = ({interpreter}: RunDisplayProps) => {
const options = useContext(OptionContext);
const index = interpreter.pointer;
let offset: number;
if (index < MAX_TABLE_COLUMNS / 2) {
offset = 0;
} else {
offset = index - MAX_TABLE_COLUMNS / 2;
}
const arrayWithIndex = Array(MAX_TABLE_COLUMNS).fill(0)
.map((_, i) => i + offset);
return (
<div>
<table className="memory-display-table">
<thead>
<tr>
{
arrayWithIndex.map((n => <th key={n}>{n}</th>))
}
</tr>
</thead>
<tbody>
<tr>
{
arrayWithIndex.map((n) => <MemoryCell key={n} index={n} interpreter={interpreter}/>)
}
</tr>
{
options.asciiView &&
<tr>
{
arrayWithIndex.map((n) => <MemoryCell key={n} index={n} interpreter={interpreter} ascii/>)
}
</tr>
}
<tr>
{
arrayWithIndex.map((n) => <td className="pointer"
key={n}>{interpreter.pointer === n && "^"}</td>)
}
</tr>
</tbody>
</table>
</div>
);
};
interface MemoryCellProps {
index: number,
interpreter: Interpreter,
ascii?: boolean,
}
const MemoryCell = ({index, interpreter, ascii}: MemoryCellProps) => {
const [isEditing, setIsEditing] = useState(false);
const [input, setInput] = useState(interpreter.array[index] + "");
const inputField = useRef<HTMLInputElement>(null);
const saveAndQuit = () => {
interpreter.array[index] = +(input);
setIsEditing(false);
}
const click = () => {
setIsEditing(true);
inputField.current?.select();
}
const keyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
console.log("key", e.key);
if (e.key === "Escape") {
setIsEditing(false);
} else if (e.key === "Enter") {
saveAndQuit();
}
}
const content = ascii ?
String.fromCharCode(interpreter.array[index])
:
interpreter.array[index];
return (
<td onClick={click} className="cell">
{
isEditing && !ascii ?
<input onKeyDown={keyDown}
className="array-set-value-field"
ref={inputField}
onChange={e => setInput(e.target.value)}
value={input}
onBlur={saveAndQuit}
autoFocus
/>
:
content
}
</td>
);
}
export default RunDisplay;

View file

@ -1,189 +0,0 @@
import React, {useCallback, useContext, useEffect, useRef, useState} from 'react';
import Interpreter from "../brainfuck/Interpreter";
import CodeDisplay from "./CodeDisplay";
import RunDisplay from "./RunDisplay";
import {OptionContext} from "./App";
interface RunInfoProps {
running: boolean,
setRunning: (running: boolean) => void,
code: string,
outHandler: (char: number) => void,
}
const Runner = ({setRunning, running, outHandler, code}: RunInfoProps) => {
const [speed, setSpeed] = useState(0);
const [interpreter, setInterpreter] = useState<Interpreter | null>(null);
const [info, setInfo] = useState<string | null>(null);
const [startTime, setStartTime] = useState(0);
const [, setRerenderNumber] = useState(0);
const rerender = () => setRerenderNumber(n => n + 1);
const options = useContext(OptionContext);
const inputArea = useRef<HTMLTextAreaElement>(null);
const inputHandler = () => {
if (!inputArea.current) {
throw new Error("Could not read input")
}
const value = inputArea.current.value;
if (value.length < 1) {
throw new Error("No input found");
}
const char = value.charCodeAt(0);
inputArea.current.value = value.substr(1);
return char;
}
const startHandler = useCallback(() => {
if (options.directStart) {
if (options.startSuperSpeed) {
setSpeed(-1);
} else {
setSpeed(100);
}
} else {
setSpeed(0);
}
setStartTime(Date.now);
setInterpreter(new Interpreter([code, options], outHandler, inputHandler));
setRunning(false);
setRunning(true);
}, [options, code, outHandler, setRunning]);
const stopHandler = () => {
setRunning(false);
setInfo(null);
}
const nextHandler = useCallback(() => {
setInfo(null);
try {
interpreter?.next();
} catch (e) {
setInfo(e.message);
setSpeed(0);
}
if (interpreter?.reachedEnd) {
setSpeed(0);
setInfo(`Finished Execution. Took ${(Date.now() - startTime) / 1000}s`)
}
rerender();
}, [interpreter, startTime]);
const runBlocking = useCallback(() => {
try {
while (speed === -1 && !interpreter?.reachedEnd) {
interpreter?.next();
}
setSpeed(0);
setInfo(`Finished Execution. Took ${(Date.now() - startTime) / 1000}s`)
} catch (e) {
setInfo(e.message);
setSpeed(0);
}
}, [speed, interpreter, startTime]);
useEffect(() => {
if (running) {
if (speed === 0) {
return;
}
if (speed > 0) {
const interval = setInterval(() => {
nextHandler();
}, 1000 / (speed * 10));
return () => clearInterval(interval);
}
runBlocking();
}
}, [runBlocking, running, nextHandler, speed]);
return (
<div className="bf-run">
{
running && interpreter && <>
<CodeDisplay code={interpreter.code} index={interpreter.programCounter}/>
<RunDisplay interpreter={interpreter}/>
</>
}
<div>
{running && <button className="run-button" onClick={stopHandler}>Back</button>}
<button className="run-button" onClick={startHandler}>{running ? "Restart" : "Start"}</button>
{running && <button className="run-button" onClick={nextHandler}>Next</button>}
</div>
{
running && interpreter &&
<>
<SpeedControl speed={speed} setSpeed={setSpeed}/>
<ManualControlButtons interpreter={interpreter} rerender={rerender}/>
</>
}
{info && <div className="info">{info}</div>}
{
running && <div>
<div>Input:</div>
<textarea className="program-input-area" ref={inputArea}/>
</div>
}
</div>
);
};
interface SpeedControlProps {
speed: number,
setSpeed: React.Dispatch<React.SetStateAction<number>>,
}
const SpeedControl = ({speed, setSpeed}: SpeedControlProps) => {
return (
<div className="speed-control-wrapper">
<label htmlFor="run-info-speed-range">Speed</label>
<input type="range" id="run-info-speed-range" value={speed}
onChange={e => setSpeed(+e.target.value)}/>
<span> {speed}</span>
<span>
<button onClick={() => setSpeed(s => s === 0 ? 0 : s - 1)}
className="small-speed-button">-</button>
<button onClick={() => setSpeed(0)}
className="small-speed-button">0</button>
<button onClick={() => setSpeed(s => s === 100 ? 100 : s + 1)}
className="small-speed-button">+</button>
</span>
<span>
<label>Superspeed Mode (blocking)</label>
<input id="superspeed-mode-check" type="checkbox" checked={speed === -1} onChange={() => setSpeed(-1)}/>
</span>
</div>
)
}
const ManualControlButtons = ({interpreter, rerender}: { interpreter: Interpreter, rerender: (() => void) }) => {
const run = (char: string) => {
try {
interpreter.execute(char);
} catch {
}
rerender();
}
return (
<div>
<button onClick={() => run('<')} className="small-speed-button">&lt;</button>
<button onClick={() => run('>')} className="small-speed-button">&gt;</button>
<button onClick={() => run('-')} className="small-speed-button">-</button>
<button onClick={() => run('+')} className="small-speed-button">+</button>
<button onClick={() => run('.')} className="small-speed-button">.</button>
</div>
)
}
export default Runner;

View file

@ -1,13 +0,0 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View file

@ -1,11 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
/// <reference types="react-scripts" />

View file

@ -1,26 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}

File diff suppressed because it is too large Load diff

2
js/.gitignore vendored
View file

@ -1,2 +0,0 @@
node_modules
.idea

View file

@ -1,4 +0,0 @@
{
"singleQuote": true,
"printWidth": 100
}

View file

@ -1 +0,0 @@
hello...[[].]]

View file

@ -1,11 +0,0 @@
{
"name": "brainfuck",
"version": "1.0.0",
"main": "src/index.js",
"license": "MIT",
"type": "module",
"devDependencies": {
"prettier": "^2.6.2"
},
"dependencies": {}
}

View file

@ -1,113 +0,0 @@
import fs from 'fs';
const RED = '\x1B[1;31m';
const RESET = '\x1B[1;0m';
function lex(string) {
const tokens = [];
for (let i = 0; i < string.length; i++) {
const char = string[i];
if (['+', '-', '>', '<', '.', ',', '[', ']'].includes(char)) {
tokens.push({
char,
span: i,
});
}
}
return tokens;
}
function ParseError(message, span) {
this.message = message;
this.span = span;
}
function Parser(tokens) {
this.tokens = tokens;
this.position = 0;
}
Parser.prototype.next = function () {
const token = this.tokens[this.position];
this.position++;
return token;
};
Parser.prototype.parse = function (isLoop) {
const body = [];
let nextToken;
while ((nextToken = this.next()) !== undefined) {
switch (nextToken.char) {
case '[': {
const loopBody = this.parse(true);
body.push(loopBody);
break;
}
case ']': {
if (isLoop) {
return body;
} else {
throw new ParseError('No matching `[` found', nextToken.span);
}
}
default: {
body.push(nextToken);
}
}
}
if (isLoop) {
throw new ParseError('No matching `]` found', this.tokens[this.tokens.length - 1].span);
} else {
return body;
}
};
function reportError(source, message, span) {
let lineIdx = 0;
let lastNewlineIdx = 0;
for (let i = 0; i < source.length; i++) {
const char = source[i];
if (i === span) {
break;
}
if (char === '\n') {
lineIdx++;
lastNewlineIdx = i;
}
}
const lines = source.split('\n');
const line = lines[lineIdx];
const lineNumber = String(lineIdx + 1);
const linePrefix = `${lineNumber} | `;
const lineSpan = span - lastNewlineIdx;
console.error(`${RED}error: ${message}${RESET}`);
console.error(`${linePrefix}${line}`);
console.error(`${' '.repeat(linePrefix.length + lineSpan)}${RED}^${RESET}`);
}
const file = process.argv[2];
if (!file) {
console.error('Usage: [filename]');
process.exit(1);
}
const source = fs.readFileSync(file, 'utf-8');
const tokens = lex(source);
const parser = new Parser(tokens);
try {
const ast = parser.parse(false);
console.log(ast);
} catch (parseError) {
if (!(parseError instanceof ParseError)) {
throw parseError;
}
reportError(source, parseError.message, parseError.span);
}

View file

@ -1,8 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
prettier@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032"
integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==

2
rust2/.gitignore vendored
View file

@ -1,2 +0,0 @@
target
.idea

View file

@ -1,3 +0,0 @@
imports_granularity = "Crate"
newline_style = "Unix"
group_imports = "StdExternalCrate"

1238
rust2/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,29 +0,0 @@
[package]
name = "brainfuck"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bumpalo = { version = "3.9.1", features = ["allocator_api"] }
clap = { version = "3.1.9", features = ["derive"] }
dbg-pls = { version = "0.3.2", features = ["colors", "derive"] }
owo-colors = "3.3.0"
rand = "0.8.5"
tracing = "0.1.34"
tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
[dev-dependencies]
criterion = "0.3.5"
insta = "1.14.0"
[profile.release]
debug = true
[profile.dev]
opt-level = 3
[[bench]]
name = "opts"
harness = false

View file

@ -1,5 +0,0 @@
Benchmark brainf*ck program
>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
[>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
++++++++[>++++++++++[>++++++++++[>++++++++++[>+
+++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.

View file

@ -1,44 +0,0 @@
>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>
[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<
-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<
[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++
+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-
]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+
++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>
>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++
+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------
---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++
[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------
-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.
>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<
-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.
><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++
++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++
+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++
+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<
-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.
------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-
]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]
<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++
+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->
-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<
++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++
.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----
---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[
-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]
>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<
<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<
<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+
<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>
-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---
-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-
-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]
<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[
<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++
++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.
>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++
..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]

View file

@ -1,7 +0,0 @@
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++\n++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<
++++<++++<++++>>>]++++\n+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++\n++++>++++++>++++++++[-<+
+++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->\n---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+\n
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[\n->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[
-<+]->>>++++++++++<<[-\n>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>\n+>>]<<<<<]>[-]>>[>++++++
[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++\n+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[\n
-<+]-<<]

View file

@ -1,709 +0,0 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>[-]>[-]+++++++++++++++++++++++++++.++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++.-------------------.-------
--------------------------------------.+++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++.-----------------------------------------.++++++
++++++++++++++++++.[-]+++++++++++++++++++++++++++.++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++.-------------------------------------
----.+++++++++.---------.+++++.+++++++++++++++++.++++++++++++.++++++++++++++
+++++++++++++.++++++++.------------------.+++++++++++++.+.------------------
-----------------------------------------------------------------.++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------
---.----------------------------------------------------------------------.+
+++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++.++++++++++
+++.+.------.---------------------------------------------------------------
----------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++.+++++.-------------------------------------------------------------
-----------------.++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++
+++++++++++++++++++++++++.-----------------.++++++++.+++++.--------.--------
----------------------------------------------------.+++++++++++++++++++++++
++++++++++++++++++++++++++++++++++.++++++++.[-]+++++++++++++++++++++++++++.+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.------------
----------------------------.++++++++.----------.++++.+++++++++++++++++++.++
+++++++++++++.+++++++++++++++++++++++++++.---------.+++++++++++..-----------
----.+++++++++.-------------------------------------------------------------
-----------------.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++.+++++++++++++++++++++++.-------------------------------------------
----------------------------------------------.+++++++++++++++++++++++++++++
++++++.+++++++++++++++++++++++++++++++++++++++++.---.---..+++++++++.+++.----
----------.-----------------------------------------------------------------
---.+++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++
++++++++.---.------.--------------------------------------------------------
--------------.++++++++++++++++++++++++++++.++++++++++++++++++++++++++++++++
++++++++++++.++++++++++++..----.--------------------------------------------
----------.-----------..++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++...-----------------------------------------------------
--------------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++.+
++++++++.---.---..+++++++++.+++.--------------.-----------------------------
-------------------------.++++++++++++++++++++++++++++++++++++++++++++++++++
+.+++++++++++++++++++.------------------------------------------------------
---------------.+++++++++++++++++++++++++++++++++++++++++++++++++++.++++.---
.+++++++++++++.+++++.-------------------------------------------------------
---------------.+++++++++++++++.[-]>[-]+++++++++>[-]+++>>[-]>[-]<<<<<[->>>>>
+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<
<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-
<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-]++++++++++++++++++++++
+++++++++++++++++++++++>[-]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<+++++++++
++++++++++++++++++++++++++++++++++>]<<<[>>>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<<
->>>][-]++++++++++++++++>[-]++++++++++++++>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<
<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[
[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>
>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-
]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>
>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<
[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+
>>>>>>>>][-]+++++++++++++++++++++++++<<<[-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-]
[-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<
<+>>>>->>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>->>>>]>[-]
>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-
]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+
>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>
>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>
]<<<[[-]<<<<----->>>>][-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<
+>>>>>>->>>][-]+++++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>
>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[
-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<
+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]
>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<
<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>
+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[
-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>
]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+
+++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-
<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->
>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<
[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>
]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>
>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]
<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[
[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>
[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<
<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>
>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->
[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[
-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<
<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<
<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[-
>>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<+++
+++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++
+++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<
]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++++++++++++++++++
+++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.
>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]
<<]<<<<<<--------------------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>
>>[-<+<<<<<+>>>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++
+++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<
+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+
<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]
>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>
>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>
>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[
-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>
>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]
>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<
+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->
>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>
->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[
-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>
>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]+++++
+++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[
[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[
->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+
>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+
<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>]
[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-
<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]
[-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<
<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>
[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]
<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>
[-]+<[[-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<+++++++++++++
+++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++++++++
+++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<+++++++
+++++++++++++++++++++++++++++++++++++++++.<+++++++++++++++++++++++++++++++++
+++++++++++++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++
++++++++.>>>>>>]<<]<<<<<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>
>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<
+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<[->>>>>>>>+<<<
<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..
>>>-]<<<.>>>>>[-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>>>>[-]>>[-<<<<<<<<+>>>>>>+>>
][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[->>>>>>>+<<<<<
<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>
+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]
>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<<<]>>>[-]<<<<
<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]<<<<<<<[-]<[-]<[-]>>>>>>>>>>[-]<<<<<[->>>
>>+<<<<<]>>>>>[-<<<<<+<<<+>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>]<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-
[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>+<<<<
<]>>>>>[[-<<<<<+>>>>>]<<<<<->>>>>]<]<<<<<+>>[-]+>>[-]>[-]<<<<<[->>>>>+<<<<<]
>>>>>[-<+<<<<+>>>>>][-]++++++++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<
<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<
<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<]<<<[-]>[-]+>[-]++>[-]++++++++>[-]
+>[-]+[>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++<<[-]>>>[-]>[
-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<-
>->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>
]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->+<]>[[-<+>]<<<[-]+>>>]<<<[>[-
]<<<<<[->>>>>+<<<<<]>>>>>[[-<<<<<+>>>>>]>[-]>[-]>[-]>>[-]>[-]<<<<<<<<<<[->>>
>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<
<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[
-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]
+>[-]+>>]>[-]>[-]<<<<<<<<<<[->>>>>>>>>>+<<<<<<<<<<]>>>>>>>>>>[-<+<<<<<<<<<+>
>>>>>>>>>][-]+++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->
+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<[-]+>>[-]+>][-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-
]>>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>[-]>[-<
<<<<<<<<<<<<<<+>>>>>>>>>>>>>>+>]<[<+>-]>[-]<<<<<<<<<<<<<<[->>>>>>>>>>>>>>+<<
<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>]<[<+++>-]>[-]
<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>[-]>[-<<<<<<<<<<<<<+>
>>>>>>>>>>>+>]<[<+++++++++>-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<[->>+<<]>>[-<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<
<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>
>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<<<<<<<]>>>>>>>>>>>>[-<
<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<
<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<+<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]
<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<
<<]>>>>>>>>>>>[-<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<
<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-<<<<<<<<
<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<
<<<+>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>+>>>>>>>>>>>>>][-]<<[->>+<<]>>[[-<<+>>]>[-]<<<<<<<<<<<<[->>>>
>>>>>>>>+<<<<<<<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<
<<<<[->>>>>>>>>>>+<<<<<<<<<<<]<[-]>>>>>>>>>>>>[-<<<<<<<<<<<+<+>>>>>>>>>>>>][
-]<<<<<<<[->>>>>>>+<<<<<<<]<<<<[-]>>>>>>>>>>>[-<<<<<<<+<<<<+>>>>>>>>>>>]<<<<
<<<<<<->[-]>+>>>>>>>][-]<[->+<]>[[-<+>]>[-]<<<<<<<<<<<<[->>>>>>>>>>>>+<<<<<<
<<<<<<]>>>>>[-]>>>>>>>[-<<<<<<<<<<<<+>>>>>+>>>>>>>][-]<<<<<<<<<<<<<[->>>>>>>
>>>>>>+<<<<<<<<<<<<<]>[-]>>>>>>>>>>>>[-<<<<<<<<<<<<<+>+>>>>>>>>>>>>][-]<<<<<
<<[->>>>>>>+<<<<<<<]<<<<<<[-]>>>>>>>>>>>>>[-<<<<<<<+<<<<<<+>>>>>>>>>>>>>]<<<
<<<<<<<->[-]>+>>>>>>>]<<<<]>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>
>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<
<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<
]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-
<+>]<<<[-]>>>]<<<[[-]>>>>[-]++>>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<
<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[
<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-
]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[-
>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>
>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<
<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[
-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<
<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[-]+>>
>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<
[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>[-]>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>]<]>[-]
>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<
<<<<<<<<<<+>>>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<
+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<
[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>
>>>>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<
<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+
<<<<]<<>>>>]>>[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<
<<<[->>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>
>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+
<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>[-]>>>>>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]
<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>
>+<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>[-<+<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>][-]++<<[
-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]
+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>
>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-
]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>[-]<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>>>>-]<<<<]<<
[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<
<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>
>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]
<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>[-]<<<<<[->>>>>
+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<+>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>
>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+
>>>>-]<<<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<
<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>
][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>
>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>
[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]
<<<[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]
<<<<<[->>>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<<<
]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[
->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]
++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<
[-]>>>]<<<[[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-
]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<<<<<[->>
>>>+<<<<<]>>>>>[-<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>][-]<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>>[<<<<+>>>>-]<-[<<<<+>>>>-]<<
<<]<<[-]>>>[<<<+>>>-]<<[>>>>]><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>
>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<
+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>
>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>>>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<
<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>>>]<]>[-]>[-]
<<<<<<<<<<<<<[->>>>>>>>>>>>>+<<<<<<<<<<<<<]>>>>>>>>>>>>>[-<+<<<<<<<<<<<<+>>>
>>>>>>>>>>][-]++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->
+<]>[[-<+>]<<<[-]>>>]<<<[[-]>[-]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>+>>>]<]<[->>>>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]>>[-]<<
<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>[-]>>>>
>[-<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>+>>>>>][-]<<<<<<<<[->>>>>>>>+<<<<<<<<]>>>
>[-]>>>>[-<<<<<<<<+>>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++>>-<]>[[-
]>[-]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>[-]>>>>>
[-<<<<<<<<<<<<<<<<+>>>>>>>>>>>+>>>>>][-]<<<<<<<[->>>>>>>+<<<<<<<]>>>[-]>>>>[
-<<<<<<<+>>>+>>>>]<<<[-]++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++>>]<[-]++++++++++++++++>[-]+++++++++++++
+>>>>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][
-]<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-
<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<
[-]>>>]<<<[[-]<<<<+++++>>>>]>[-]>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>
[-<+<<<<<<<<+>>>>>>>>>][-]+<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<
<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>
>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]
>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[[-]<<<++++++++++>>>][-]>[-]<<<<<<<<[->>>
>>>>>+<<<<<<<<]>>>>>>>>[-<+<<<<<<<+>>>>>>>>][-]+++++++++++++++++++++++++<<<[
-]>>[>>[-]<[->+<]>[-<+<<<+>>>>]<<-][-]<<[->>+<<]>>[-<<+<<+>>>>][-]<<<<<<<<<<
<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>][-]<<<<<<<<
<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>>>[-<<<<<<<<<<<+>>>>>>>->>>>]>[-]>[-]<
<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<+<<<<<<<<+>>>>>>>>>][-]++<<[-]+>>>
[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]
<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[
-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<<[
[-]<<<<----->>>>][-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<<<<<<+>>>->>>][-]++++++++
+++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++.>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>]>>>[-]>[-]<<<<<[->>>
>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>
+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<
[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<
<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>
[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[
-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<
<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<
<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<
<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<
+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>
>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>
[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<
<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++
>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]
<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<
<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+
<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]
<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++++++++++++++++++
++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.<++
++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<
<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++++++++++++++++++
++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-<]>[[-]<<<<<<+++
+++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<<<--------------
------------------.>[-]>[-]<<<<<<[->>>>>>+<<<<<<]>>>>>>[-<+<<<<<+>>>>>>]>>>[
-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->
>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]
>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[->+<]>[[-<+>
]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]>[-]<<<<<[->
>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-
]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<
<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<
<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++
++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<
<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<[-]>>>>
>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<->>>>]>]<<<[
-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-
]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+
>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>
>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>
>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]
<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>>]<<[-<<<->>
>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>
>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>
[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>
>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>]<++++++++++
++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++
++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>-<]>[[-]>
[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++++++++++++++
++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>-
<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>>>>>]<<]<<<<
<<+++++++++++++.>[-]>[-]<<<<<<<[->>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][
-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++<<[-]+>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>
>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<
]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[-]+++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++.<-<]>[[-]<<<<<<.>>>>>>]<[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>
>[-]>>[-<<<<<<<<<<<+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]
<<<.>>>>>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>>>>[-]>>[-<<<<<<<<<<<
+>>>>>>>>>+>>][-]<<[->>+<<]>>[[-<<+>>]<<->>]<<[<<<..>>>-]>>>[-]>[-]<<<<<<<[-
>>>>>>>+<<<<<<<]>>>>>>>[-<+<<<<<<+>>>>>>>][-]+++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<[-]+>>>[-]>[-]<<<
[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]
[-]<<[->>+<<]>>[[-<<+>>]<<<[-]>>>][-]<[->+<]>[[-<+>]<<<[-]>>>]<<[-]+<[[-]>>[
-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++.<-<]>[[-]<<<<<<.>>>>>>]<<<<<<
<<<]>[-]++++++++++.[-]+>[-]+>[-]+++++++++++++++++++++++++++.++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++.>[-]>[-]<<<[->>>+<<<]>>>[-<
+<<+>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<
[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<
<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[
-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[-]<[
->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<<[-]
>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>[-]<
<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>
>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<+>>]
<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>
][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>
>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<
<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<
<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-<<<<
->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[
-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>
]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]
>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+
<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>
[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<
[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<
->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]
<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+>>>>
>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++
++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<
<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>
>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-
]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[-<+>
]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++
++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++++.>
>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++++++
++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++
++++.>>>>>>-<]>[[-]<<<<<<++++++++++++++++++++++++++++++++++++++++++++++++.>>
>>>>]<<]<<<<<<--------------------------------.>[-]>[-]<<<<[->>>>+<<<<]>>>>[
-<+<<<+>>>>]>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++>[
-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>
>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<]<<<]<<<[-]>>>>>>[
-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<<+>>>>>>>]<<[-<<<<<->>>>>]>]<<
<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<<<<[-]>>>>[>>>
[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[-
>>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<
<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[->>+<<]>>[[-<<
+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>
>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<
<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[
-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<
]<]<<<]<<[-]>>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<<+>>>>>>]<<[-
<<<<->>>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++++++++<<
<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+
>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<[->>>>+<
<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]+>[-]<<[
->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]>[-]<<<<<[->>>>>+<<<<<]>
>>>>[-<+<<<<+>>>>>][-]++++++++++>[-]<<[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]
<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<
[<<<->>->[-]>[-]<<<<[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+
>>>]<<[-]+>>]<]<]<<<]<[-]>>>>[-]<[->+<]>[[-<+>]>[-]<<<[->>>+<<<]>>>[-<<<+<<+
>>>>>]<<[-<<<->>>]>]<<<[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<<<+>>>>>][-]++++
++++++<<<<<[-]>>>>[>>>[-]<<[->>+<<]>[-]>[-<<+>+>][-]>[-]<<<<[->>>>+<<<<]>>>>
[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<<->>->[-]>[-]<<<<
[->>>>+<<<<]>>>>[[-<<<<+>>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]
+>[-]<<[->>+<<]>>[[-<<+>>]<[-]>]<[[-]<<<<<<<+>>>>>>>]<<<][-]<[->+<]>>[-]+<[[
-<+>]<++++++++++++++++++++++++++++++++++++++++++++++++.<++++++++++++++++++++
++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++++++++
++.>>>>-<]>[[-]>[-]<<<<[->>>>+<<<<]>>>>>[-]+<[[-<<<<+>>>>]<<<<++++++++++++++
++++++++++++++++++++++++++++++++++.<++++++++++++++++++++++++++++++++++++++++
++++++++.>>>>>>-<]>[[-]<<<<<<+++++++++++++++++++++++++++++++++++++++++++++++
+.>>>>>>]<<]<<<<<<+++++++++++++.<<[-]+++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++[>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[>[-]+++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++[-]<-]<-]<<<<<]<<<<+>>>>[-]>[-]<<<<<[->>>>>+<<<<<]>>>>>[-<+<<
<<+>>>>>][-]++++<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>
>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->
>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<<[->>+<<]>>[[-<<+>>]<<<[-]+>>>][-]<[->
+<]>[[-<+>]<<<[-]+>>>]<<<]<<->>[-]<<[->>+<<]>>[[-<<+>>]<<<<<<<<-<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[-]<[-]<[-]>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>
>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>-[<<<<+>
>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-]>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>[-]>>>>>[-]<<<<<<<<<[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>>>
-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]<[-]<[-
]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[-]>>>>[-]<<<<<<<<<[
->>>>>>>>>+<<<<<<<<<]>>>>>>>>>[-<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[<<<[-]<[-]<[-]+>>>
>>-[<<<<+>>>>-]<<<<]<<[->>+>+<<<]>>[-<<+>>]<[>>[->>>>+<<<<]<<>>>>]>>[->>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[-]>[-]>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<<<<]>>>>>>
>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]>
[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<<<]>>>[[-<
<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<+>]<<<[-]+
>>>]<<<[<<<<<<<<--------->>+>>>>>>>[-]++++++++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>
>>+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>
>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-
]<<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<
[->+<]>[[-<+>]<<<[-]+>>>]<<<]>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>+<<<<<<<<
<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+<<<]>>>[[
-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<<<[->>>+<
<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[->+<]>[[-<
+>]<<<[-]+>>>]<<<[<<<<<<<<--->+>>>>>>>>[-]++>[-]>[-]<<<<<<<<<<<[->>>>>>>>>>>
+<<<<<<<<<<<]>>>>>>>>>>>[-<+<<<<<<<<<<+>>>>>>>>>>>]<<<[-]>>>[-]>[-]<<<[->>>+
<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<[<<->->[-]>[-]<
<<[->>>+<<<]>>>[[-<<<+>>>]>[-]<<<[->>>+<<<]>>>[[-<<<+>>>]<<[-]+>>]<]<][-]<[-
>+<]>[[-<+>]<<<[-]+>>>]<<<]<<<<+>>>]<<]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

View file

@ -1,212 +0,0 @@
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[
-]<<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+<<<<<<<<>+++++<>[<>-
<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>>+<<<<<<<<>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>[<<<>>>
>>>>>>[>>>>>>>[-]<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[-]+<<<<<<<
>++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<>++
+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<<<<
<<<<<<[<<<<<<<<<]>>>[<<<>>>[-]<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<
<<<<<>[-<>>>>>>>+<<<<<<<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<
]>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>
>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[<<<<<<<>>>>>>
>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<
<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>
>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+<<
>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>
>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->
>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[
<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>>>
]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<
<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>>>
+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<
>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[-
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-<<
<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>
>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++
+++++++++++++++++++++<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>[-]<<]>>[<<<<<<<
+<[-<+>>>>+<<[-]]>[-><<<[->+>>>-<<<<]>>>]>>>>>>>>>>>>>[>>[-]<<>>>[-]<<<>
>>>[-]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>>>>>>[>>>>>[-<<<<<>
+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>
>>>[>>[-<<<<<<<<<+>>>>>>>>>]<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++
+++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>[-<<+
>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<
<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<
<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<[->+<]>>>]<<<
>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>
>>>>>+<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>
>>+<<<<<<[->>[-<<+>>]<<[->>+<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]
<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>
>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>
>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<
<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]
<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>
>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>
>>>-<<<<<>>>>-<<<<+>>>>>]<<<<<>>>>>>[<<<<<<>>>>>>-<<<<<<[->>>>>+<<<<<>>>
>+<<<<>>>>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>
>>>>]<<<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>+<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]>
>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>[-<<->>]+<<
[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[
>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+>>]<<[->>+<<<<<<<<<<<[<
<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<
<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>
>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>
+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>>+<<<<<<>>>]
<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>>
+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>
>>>+<<<<<<>>>]<<<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>
>[>+<>>[-<<>-<>>]<<>[-<>>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>+<<<<<<>
>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>[-<<>>>>>>+<<<<<<>>]<<>>>]<<<
>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>]<>>>[-<<<>>>>>>+<<<<<<>>[
-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>>>]<<<>>[-<<>>>>>>+<<<<<<>>]<
<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<[>[-<>>>>>>+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><
>>>[-<<<>>>>>>+<<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>
>><>>>]<<<>]<>>[-<<>>>>>>+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>
><>>>]<<<>>]<<>>>[-<<<>>>>>>+<<<<<<>>>]<<<<<<<<<<<<]]>[-]<>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[
>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>
>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<
<<<<[->>[-<<+>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>
>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<
<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>
>>>>>]<<<<<<<<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<
[->+<]>>>]<<<>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<
<<<<<<<[<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<
<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[-+>>>[-<<<->>>
]+<<<[->>>-<<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]
+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+
>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<
]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>
]<<<[->>>+<<<>>>>>>>>>[>+<>>>>[-<<<<>-<>>>>]<<<<>[-<>>>>+<<<<>]<>>>>>>>>
>]<<<<<<<<<>+<[>[-<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>[-<<<<>>+<
<>>>>]<<<<>>>]<<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>]<>>>[-<<
<>>+<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>>>]<<<>>>>[-<<<<>>+<
<>>>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<
<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>+<<>>>>[-<<<<>>-<<
><<<<<<<<<+>>>>>>>>><>>>[-<<<>>+<<>>>]<<<>>>>]<<<<>>>[-<<<>>-<<><<<<<<<<
<+>>>>>>>>><>>>]<<<>]<>>>>[-<<<<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>
>>]<<<>>>>]<<<<>>>[-<<<>>+<<>>>]<<<<<<<<<<<<]>>>>>+<<<<<]>>>>>>>>>[>>>[-
]<<<>>>>[-]<<<<>>>>>[-]<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<>>>
+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>
-<<<<+>>>>>]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<[->>>>>+<<<<<>>>>+<<<<>>>
>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>>>>>>]<<<
<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]+>>>>[
-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+
>>]<<[->>+<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>
[-<<->>]+<<[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<
<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>>[>+<>>[-<<>-<>>]<<>[-<>
>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<
<<+>>>>>>>>><>>[-<<>>>>>+<<<<<>>]<<>>>]<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>
>>>>>>><>>]<<>]<>>>[-<<<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>>
<>>]<<>>>]<<<>>[-<<>>>>>+<<<<<>>]<<<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>[<<<<<<
<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]]>>>>[-<<<<
+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>
>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>
>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>
]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>
>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>>>]<<<
<[->>>>+<<<<>>>>>[-]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[
->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-<>>>>>+<<<<
<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>
>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<
<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<
<<<<<<<<]]>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]
<<<>>>>[-]<<<<>>>>>>>>>[>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]
<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++
+++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>
>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+
<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<
<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>
>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<
>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]
>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>
>>]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[
>>>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<
<<<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>
>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<
<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>
[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>
>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-
<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>
>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<
<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<
<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>-<<>>>>[-<<<<+>>>>]<<<<[->>>>+
<<<<>>[-]<<]>>]<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[<<<<>>>>-<<
<<<<<.>>>>>>>]<<<<>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<>>>>>>>>>[>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]<<<<<>>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<
>]<>>>>>>>>>>]<>>>>>+<<<<<>>>>>>>>>>>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>
>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>[-]<<<<<<<>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<[
<<<<<<<<<]>>>>>>>[-]+<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>[-<<<<<<<+>>>>
>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>>>[>+<>>>>>[-<<<<<>-<>>>>>]<<<<<>[-<>
>>>>+<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>+<<<<<<<[>>>>>[<<<<<>>>>>-<<<<<>>
>>>>>+<<<<<<<>>>>>]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<->>
>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>>]<
[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>>>>>>>-<<<<<<<>
>>[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>>>>>[>
>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>
>]<[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<
>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>+<<<<<[<<<<<<<<<]>>>>>>>>
>[-+>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>-<<<<<>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<
<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>
+<]]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>[-<<<<<+>>>>
>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[
-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<
<<<>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>-<<<<<[<<
<<<<<<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<
<]>+++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<
<<>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>>>>>]
<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>[-]<<<<<<<<>>>>>>>>>[>>>>>>>>>]<<<<<<
<<<[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<[<<<<<<<<
<]>>>>>>>>[-]+<<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<<<<+>>>>>>>>
]<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>>[>+<>>>>>>[-<<<<<<>-<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>>+<<<<<<<<[>>>>>>[<<<<<<>>>
>>>-<<<<<<>>>>>>>>+<<<<<<<<>>>>>>]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<
<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>
>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<<<>[<>-<>>>>>>>>+<<<<<<<<>]<+
<<<<<<<<<]>>>>>>>>-<<<<<<<<>>>[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>>>>[>>>>>>[<<<<<<>>>>>>-<<<<<<>>>>>>>>+<<<<
<<<<>>>>>>]<<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<
<<<<<+>[<->-<<<<<<<<<<>>>>>>>>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<
<<>[<>-<>>>>>>>>+<<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<
<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
<<<[<<<<<<<<<]>>>>>>>>>[-+>>>>>>[-<<<<<<->>>>>>]+<<<<<<[->>>>>>-<<<<<<>>
>>>>>>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<<>+++++<>[<>-<>[<>-<>>>>
>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>-<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>-<<<<<<[<<<<<<<<<]]>>>]<<<

View file

@ -1,55 +0,0 @@
use std::io::{Read, Write};
use bumpalo::Bump;
use criterion::{black_box, criterion_main, Criterion};
struct MockReadWrite;
impl Read for MockReadWrite {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
buf.fill(b'A');
Ok(buf.len())
}
}
impl Write for MockReadWrite {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
fn run_bf(bf: &str) {
let bump = Bump::new();
let ast = brainfuck::parse::parse(&bump, bf.bytes().enumerate()).unwrap();
let hir = brainfuck::hir::optimized_hir(&bump, &ast);
let lir = brainfuck::lir::generate(&bump, &hir);
brainfuck::lir::interpreter::run(&lir, MockReadWrite, MockReadWrite, |_| {});
}
fn optimized(c: &mut Criterion) {
let fizzbuzz = include_str!("fizzbuzz.bf");
let bench = include_str!("bench.bf");
let twinkle = include_str!("twinkle.bf");
let bottles = include_str!("bottles.bf");
let mandelbrot = include_str!("mandelbrot.bf");
let hanoi = include_str!("hanoi.bf");
c.bench_function("fizzbuzz", |b| b.iter(|| run_bf(black_box(fizzbuzz))));
c.bench_function("bench", |b| b.iter(|| run_bf(black_box(bench))));
c.bench_function("twinkle", |b| b.iter(|| run_bf(black_box(twinkle))));
c.bench_function("bottles", |b| b.iter(|| run_bf(black_box(bottles))));
c.bench_function("mandelbrot", |b| b.iter(|| run_bf(black_box(mandelbrot))));
c.bench_function("hanoi", |b| b.iter(|| run_bf(black_box(hanoi))));
}
pub fn benches() {
// we need such a low sample size because the benches take ages otherwise
let mut c = Criterion::default().configure_from_args().sample_size(30);
optimized(&mut c);
}
criterion_main!(benches);

File diff suppressed because one or more lines are too long

View file

@ -1,212 +0,0 @@
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[
-]<<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+<<<<<<<<>+++++<>[<>-
<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>>+<<<<<<<<>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>[<<<>>>
>>>>>>[>>>>>>>[-]<<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[-]+<<<<<<<
>++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<>++
+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>>+<<<<<<<<<<
<<<<<<[<<<<<<<<<]>>>[<<<>>>[-]<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<
<<<<<>[-<>>>>>>>+<<<<<<<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<
]>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>
>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>[<<<<<<<>>>>>>
>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>+++++++++
+++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<
<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>
>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+<<
>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>
>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->
>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[
<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>>>
]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<
<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>>>
+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<
>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[-
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-<<
<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>
>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++
+++++++++++++++++++++<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>[-]<<]>>[<<<<<<<
+<[-<+>>>>+<<[-]]>[-><<<[->+>>>-<<<<]>>>]>>>>>>>>>>>>>[>>[-]<<>>>[-]<<<>
>>>[-]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>>>>>>[>>>>>[-<<<<<>
+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>
>>>[>>[-<<<<<<<<<+>>>>>>>>>]<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++
+++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>[-<<+
>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<
<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<
<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<[->+<]>>>]<<<
>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>
>>>>>+<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>
>>+<<<<<<[->>[-<<+>>]<<[->>+<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]
<>]<>>>>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>
>]<<<<<<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>
>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<
<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>[
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<
[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]
<<<<<<<<>[-<>>>>>>>>+<<<<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>
>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>
>>>-<<<<<>>>>-<<<<+>>>>>]<<<<<>>>>>>[<<<<<<>>>>>>-<<<<<<[->>>>>+<<<<<>>>
>+<<<<>>>>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>
>>>>]<<<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>+<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]>
>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>[-<<->>]+<<
[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[
>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+>>]<<[->>+<<<<<<<<<<<[<
<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<
<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>
>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>
+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>>+<<<<<<>>>]
<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>>
+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>
>>>+<<<<<<>>>]<<<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>
>[>+<>>[-<<>-<>>]<<>[-<>>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>>+<<<<<<>
>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>[-<<>>>>>>+<<<<<<>>]<<>>>]<<<
>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>]<>>>[-<<<>>>>>>+<<<<<<>>[
-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><>>]<<>>>]<<<>>[-<<>>>>>>+<<<<<<>>]<
<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>>>>>
>>>>]<<<<<<<<<[>[-<>>>>>>+<<<<<<>>[-<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>><
>>>[-<<<>>>>>>+<<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>
>><>>>]<<<>]<>>[-<<>>>>>>+<<<<<<>>>[-<<<>>>>>>-<<<<<<><<<<<<<<<+>>>>>>>>
><>>>]<<<>>]<<>>>[-<<<>>>>>>+<<<<<<>>>]<<<<<<<<<<<<]]>[-]<>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[
>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]<>>>>>>>>>]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>
>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<
<<<<[->>[-<<+>>]<<[->>+<<>>>+<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>
>>>>>>>[>>>>>>>>>]<<<<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<
<<<<<<>]<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>
>>>>>]<<<<<<<<<[>[-]<->>>[<<<>>>-<<<+>[<->-<<<<<<<<<<>>>+<<<>>>>>>>>>>]<
[->+<]>>>]<<<>[<>-<>>>+<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]<<<>>>>>>>>>]<<
<<<<<<<[<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>>>++++++++++++++++-[[>>>>>>>>>]<<<
<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[-+>>>[-<<<->>>
]+<<<[->>>-<<<>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]
+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+
>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<
]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>
]<<<[->>>+<<<>>>>>>>>>[>+<>>>>[-<<<<>-<>>>>]<<<<>[-<>>>>+<<<<>]<>>>>>>>>
>]<<<<<<<<<>+<[>[-<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>[-<<<<>>+<
<>>>>]<<<<>>>]<<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>]<>>>[-<<
<>>+<<>>>>[-<<<<>>-<<><<<<<<<<<+>>>>>>>>><>>>>]<<<<>>>]<<<>>>>[-<<<<>>+<
<>>>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<
<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>+<<>>>>[-<<<<>>-<<
><<<<<<<<<+>>>>>>>>><>>>[-<<<>>+<<>>>]<<<>>>>]<<<<>>>[-<<<>>-<<><<<<<<<<
<+>>>>>>>>><>>>]<<<>]<>>>>[-<<<<>>+<<>>>[-<<<>>-<<><<<<<<<<<+>>>>>>>>><>
>>]<<<>>>>]<<<<>>>[-<<<>>+<<>>>]<<<<<<<<<<<<]>>>>>+<<<<<]>>>>>>>>>[>>>[-
]<<<>>>>[-]<<<<>>>>>[-]<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]<<<>>>>[
-]<<<<>>>>>>>>>[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<>>>
+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>
-<<<<+>>>>>]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<[->>>>>+<<<<<>>>>+<<<<>>>
>+<<<<]>>>>>[<<<<<>>>>>-<<<<<+>>>>>]<<<<<>>>>-<<<<>>>>>+<<<<<>>>>>>>]<<<
<<<<>>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<[->>>>>+<<<<<]+>>>>[
-<<<<->>>>]+<<<<[->>>>-<<<<>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>[-<<+
>>]<<[->>+<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>
[-<<->>]+<<[->>-<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<
<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<
<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+<<<>>>>>>>>>[>+<>>[-<<>-<>>]<<>[-<>
>+<<>]<>>>>>>>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<
<<+>>>>>>>>><>>[-<<>>>>>+<<<<<>>]<<>>>]<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>
>>>>>>><>>]<<>]<>>>[-<<<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>>
<>>]<<>>>]<<<>>[-<<>>>>>+<<<<<>>]<<<<<<<<<<<]>>>>>[-]<<<<<>>>>>>>[<<<<<<
<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>+<<<<<]]>>>>[-<<<<
+>>>>]<<<<[->>>>+<<<<>>>>>>>>>[>+<>>>[-<<<>-<>>>]<<<>[-<>>>+<<<>]<>>>>>>
>>>]<<<<<<<<<>+<[>[-<>>>>>+<<<<<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>
>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>
]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>
>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>>>]<<<
<[->>>>+<<<<>>>>>[-]<<<<<>>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>>>>>>>]<<<<<<<[
->>>>>>>+<<<<<<<>>>>>+<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-<>>>>>+<<<<
<>>[-<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>[-<<<>>>>>+<<<<<>>>]<<<>>]<<>>
>[-<<<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>]<>>[-<<>>>>>+<<<<<>>>[-<<
<>>>>>-<<<<<><<<<<<<<<+>>>>>>>>><>>>]<<<>>]<<>>>[-<<<>>>>>+<<<<<>>>]<<<<
<<<<<<<<]]>>>>>>>>>[>>[-]<<>>>[-]<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]
<<<>>>>[-]<<<<>>>>>>>>>[>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<>>+<<>]
<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>>>+<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++
+++++++++-[[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<
<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>
>>>>>>>>[>-<>>>>>[-<<<<<>+<>>>>>]<<<<<>[-<>>>>>+<<<<<[->>[-<<+>>]<<[->>+
<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[>>>>>>>>>]<<<
<<<<<<<>[<>>[<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>]<>>[<<>>-<<>>
>>>>>>>>>+<<<<<<<<<<<>>]<<<<<<<<<<<>>>>>>>>>>+<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<<<>>>>>>>>>>]<[->+<]>>>>]<<<<
>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>+<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]
>>>>>>>>>[>-<>>>>>>[-<<<<<<>+<>>>>>>]<<<<<<>[-<>>>>>>+<<<<<<[->>>[-<<<+>
>>]<<<[->>>+<<<>>>>+<<<<]+>>>>>>>>>]><<<<<<<<<[<<<<<<<<<]<>]<>>>>>>>>>>[
>>>>>>>>>]<<<<<<<<<<>[<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<
<<<<<<>]<>>>[<<<>>>-<<<>>>>>>>>>>>>+<<<<<<<<<<<<>>>]<<<<<<<<<<<<>>>>>>>>
>>+<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>[<<<<>>>>-<<<<+>[<->-<<<<<<<<<<>>>>+<<
<<>>>>>>>>>>]<[->+<]>>>>]<<<<>[<>-<>>>>+<<<<>]<+<<<<<<<<<]>>>>>>>>>[>>>>
[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>]<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++++++++++-[[>>>>>>
>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+<<<<<<<<<>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>+<<<[<<<<<<<<<]>>>>>>>>>[-+>>>[-<<<->>>]+<<<[->>>-<<<>>>>[-
<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>
>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<>>>[-<<<+>>>]<<<[->>>+<<<<<<<
<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<
<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>-<<>>>>[-<<<<+>>>>]<<<<[->>>>+
<<<<>>[-]<<]>>]<<+>>>>[-<<<<->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[<<<<>>>>-<<
<<<<<.>>>>>>>]<<<<>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<>>>>>>>>>[>[-]>[-]>[-]>[
-]>[-]>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]<<<<<>>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<
>]<>>>>>>>>>>]<>>>>>+<<<<<>>>>>>>>>>>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>
>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>[-]<<<<<<<>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>>>>>>[-<<<<<<<>+<>>>>>>>]<<<<<<<>[-<>>>>>>>+<<<<<<<[
<<<<<<<<<]>>>>>>>[-]+<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>[-<<<<<<<+>>>>
>>>]<<<<<<<[->>>>>>>+<<<<<<<>>>>>>>>>[>+<>>>>>[-<<<<<>-<>>>>>]<<<<<>[-<>
>>>>+<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>+<<<<<<<[>>>>>[<<<<<>>>>>-<<<<<>>
>>>>>+<<<<<<<>>>>>]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<->>
>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>>]<
[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>>>>>>>-<<<<<<<>
>>[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>>>>>[>
>>>>[<<<<<>>>>>-<<<<<>>>>>>>+<<<<<<<>>>>>]<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<
->>>>>>>[<<<<<<<>>>>>>>-<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>+<<<<<<<>>>>>>>>>
>]<[->+<]>>>>>>>]<<<<<<<>[<>-<>>>>>>>+<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<
>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>+<<<<<[<<<<<<<<<]>>>>>>>>
>[-+>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>-<<<<<>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<
<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>
+<]]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<<<<<<>>>>>[-<<<<<+>>>>
>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[
-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<
<<<>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>-<<<<<[<<
<<<<<<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]<<<<<<>>>>>>>>>]<<<<<<<<<[<<<<<<<<
<]>+++++++++<>[<>-<>[<>-<>>>>>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<
<<>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<<<+>>>>>>>>]
<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>[-]<<<<<<<<>>>>>>>>>[>>>>>>>>>]<<<<<<
<<<[>>>>>>>>[-<<<<<<<<>+<>>>>>>>>]<<<<<<<<>[-<>>>>>>>>+<<<<<<<<[<<<<<<<<
<]>>>>>>>>[-]+<<<<<<<<>>>>>>>>>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<<<<+>>>>>>>>
]<<<<<<<<[->>>>>>>>+<<<<<<<<>>>>>>>>>[>+<>>>>>>[-<<<<<<>-<>>>>>>]<<<<<<>
[-<>>>>>>+<<<<<<>]<>>>>>>>>>]<<<<<<<<<>>>>>>>>+<<<<<<<<[>>>>>>[<<<<<<>>>
>>>-<<<<<<>>>>>>>>+<<<<<<<<>>>>>>]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<
<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<<<<<<+>[<->-<<<<<<<<<<>>>>>>>
>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<<<>[<>-<>>>>>>>>+<<<<<<<<>]<+
<<<<<<<<<]>>>>>>>>-<<<<<<<<>>>[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>>>>[>>>>>>[<<<<<<>>>>>>-<<<<<<>>>>>>>>+<<<<
<<<<>>>>>>]<<<<<<>>>>>>>>>]<<<<<<<<<[>[-]<->>>>>>>>[<<<<<<<<>>>>>>>>-<<<
<<<<<+>[<->-<<<<<<<<<<>>>>>>>>+<<<<<<<<>>>>>>>>>>]<[->+<]>>>>>>>>]<<<<<<
<<>[<>-<>>>>>>>>+<<<<<<<<>]<+<<<<<<<<<]>+++++<>[<>-<>[<>-<>>>>>>>>>>+<<<
<<<<<<<>]<>>>>>>>>>>]<>>>>>>+<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<
<<<[<<<<<<<<<]>>>>>>>>>[-+>>>>>>[-<<<<<<->>>>>>]+<<<<<<[->>>>>>-<<<<<<>>
>>>>>>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+<<<<>>>>>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<
<<<<[->>>>>>>>-<<<<<<<<>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<
<<<[<<<<<<<<<]>>>[-]+<<<>>>>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<
<<<<<>]<>>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<<>+++++<>[<>-<>[<>-<>>>>
>>>>>>+<<<<<<<<<<>]<>>>>>>>>>>]<>>>>>>-<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>-<<<<<<[<<<<<<<<<]]>>>]<<<

View file

@ -1,2 +0,0 @@
[toolchain]
channel = "nightly-2022-04-17"

View file

@ -1,102 +0,0 @@
use std::fmt::{Debug, Formatter};
use bumpalo::Bump;
use dbg_pls::DebugPls;
use crate::{
parse::{Ast, Instr, Span},
BumpVec,
};
pub mod opts;
#[derive(Clone)]
pub struct Hir<'hir> {
pub stmts: BumpVec<'hir, Stmt<'hir>>,
}
impl Debug for Hir<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.stmts, f)
}
}
impl DebugPls for Hir<'_> {
fn fmt(&self, f: dbg_pls::Formatter<'_>) {
DebugPls::fmt(&self.stmts.iter().collect::<Vec<_>>(), f)
}
}
#[derive(Clone)]
pub struct Stmt<'hir> {
pub kind: StmtKind<'hir>,
pub span: Span,
}
impl<'hir> Stmt<'hir> {
fn new(kind: StmtKind<'hir>, span: Span) -> Stmt<'hir> {
Self { kind, span }
}
pub fn kind(&self) -> &StmtKind<'hir> {
&self.kind
}
}
impl Debug for Stmt<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.kind, f)
}
}
impl DebugPls for Stmt<'_> {
fn fmt(&self, f: dbg_pls::Formatter<'_>) {
DebugPls::fmt(&self.kind, f)
}
}
#[derive(Debug, Clone, DebugPls)]
pub enum StmtKind<'hir> {
Add(i32, u8),
Sub(i32, u8),
/// Sets the current cell to 0 and adds that value of the cell to another cell at `offset`
MoveAddTo {
offset: i32,
},
Right(usize),
Left(usize),
Loop(Hir<'hir>),
Out,
In,
SetN(u8),
}
fn ast_to_ir<'hir>(alloc: &'hir Bump, ast: &Ast<'_>) -> Hir<'hir> {
let mut stmts = Vec::new_in(alloc);
let stmts_iter = ast.iter().map(|(instr, span)| {
let kind = match instr {
Instr::Add => StmtKind::Add(0, 1),
Instr::Sub => StmtKind::Sub(0, 1),
Instr::Right => StmtKind::Right(1),
Instr::Left => StmtKind::Left(1),
Instr::Out => StmtKind::Out,
Instr::In => StmtKind::In,
Instr::Loop(body) => {
let ir_body = ast_to_ir(alloc, body);
StmtKind::Loop(ir_body)
}
};
Stmt::new(kind, *span)
});
stmts.extend(stmts_iter);
Hir { stmts }
}
pub fn optimized_hir<'hir>(alloc: &'hir Bump, ast: &Ast<'_>) -> Hir<'hir> {
let mut hir = ast_to_ir(alloc, ast);
opts::optimize(alloc, &mut hir);
hir
}

View file

@ -1,321 +0,0 @@
use std::cmp::Ordering;
use bumpalo::Bump;
use tracing::trace;
use crate::{
hir::{Hir, Stmt, StmtKind},
BumpVec,
};
pub fn optimize<'hir>(alloc: &'hir Bump, hir: &mut Hir<'hir>) {
pass_group(alloc, hir);
pass_find_set_null(hir);
pass_set_n(hir);
pass_cancel_left_right_add_sub(hir);
pass_add_sub_offset(hir);
pass_move_add_to(hir);
// pass_unroll_loops(hir);
// pass_cancel_left_right_add_sub(hir);
}
/// pass that replaces things like `Sub(1) Sub(1)` with `Sub(2)`
// TODO: This pass is really slow, speed it up please
#[tracing::instrument(skip(alloc, ir_param))]
fn pass_group<'hir>(alloc: &'hir Bump, ir_param: &mut Hir<'hir>) {
let empty_ir = Hir {
stmts: Vec::new_in(alloc),
};
let ir = std::mem::replace(ir_param, empty_ir);
let new_stmts = Vec::new_in(alloc);
let stmts =
ir.stmts
.into_iter()
.fold(new_stmts, |mut stmts: BumpVec<'hir, Stmt<'hir>>, next| {
let Some(old) = stmts.last_mut() else {
if let StmtKind::Loop(mut body) = next.kind {
pass_group(alloc, &mut body);
stmts.push(Stmt::new(
StmtKind::Loop(body),
next.span,
));
} else {
stmts.push(next);
}
return stmts;
};
match (&mut old.kind, next.kind) {
(StmtKind::Add(offset_a, a), StmtKind::Add(offset_b, b))
if *a < 255 && *offset_a == offset_b =>
{
old.span = old.span.merge(next.span);
*a += b;
}
(StmtKind::Sub(offset_a, a), StmtKind::Sub(offset_b, b))
if *a < 255 && *offset_a == offset_b =>
{
old.span = old.span.merge(next.span);
*a += b;
}
(StmtKind::Right(a), StmtKind::Right(b)) if *a < 255 => {
old.span = old.span.merge(next.span);
*a += b;
}
(StmtKind::Left(a), StmtKind::Left(b)) if *a < 255 => {
old.span = old.span.merge(next.span);
*a += b;
}
(_, StmtKind::Loop(mut body)) => {
pass_group(alloc, &mut body);
stmts.push(Stmt {
span: next.span,
kind: StmtKind::Loop(body),
});
}
(_, kind) => {
stmts.push(Stmt::new(kind, next.span));
}
}
stmts
});
*ir_param = Hir { stmts };
}
/// pass that replaces `Loop([Sub(_)])` to `SetNull`
#[tracing::instrument(skip(ir))]
fn pass_find_set_null(ir: &mut Hir<'_>) {
pass_find_set_null_inner(ir)
}
fn pass_find_set_null_inner(ir: &mut Hir<'_>) {
for stmt in &mut ir.stmts {
if let Stmt {
kind: StmtKind::Loop(body),
span,
} = stmt
{
if let [Stmt {
kind: StmtKind::Sub(0, _),
..
}] = body.stmts.as_slice()
{
trace!(?span, "Replacing Statement with SetNull");
*stmt = Stmt::new(StmtKind::SetN(0), *span);
} else {
pass_find_set_null_inner(body);
}
}
}
}
/// pass that replaces `SetN(n) Add(m)` with `SetN(n + m)`
#[tracing::instrument(skip(ir))]
fn pass_set_n(ir: &mut Hir<'_>) {
pass_set_n_inner(ir)
}
fn pass_set_n_inner(ir: &mut Hir<'_>) {
window_pass(ir, pass_set_n_inner, |[a, b]| {
if let StmtKind::SetN(before) = a.kind() {
let new = match b.kind() {
StmtKind::Add(0, n) => StmtKind::SetN(before.wrapping_add(*n)),
StmtKind::Sub(0, n) => StmtKind::SetN(before.wrapping_sub(*n)),
_ => {
return WindowPassAction::None;
}
};
return WindowPassAction::Merge(new);
}
WindowPassAction::None
});
}
/// pass that replaces `Left(5) Right(3)` with `Left(2)`
#[tracing::instrument(skip(ir))]
fn pass_cancel_left_right_add_sub(ir: &mut Hir<'_>) {
pass_cancel_left_right_add_sub_inner(ir)
}
fn pass_cancel_left_right_add_sub_inner(ir: &mut Hir<'_>) {
window_pass(ir, pass_cancel_left_right_add_sub_inner, |[a, b]| {
match (a.kind(), b.kind()) {
(StmtKind::Right(r), StmtKind::Left(l)) | (StmtKind::Left(l), StmtKind::Right(r)) => {
let new = match r.cmp(l) {
Ordering::Equal => {
return WindowPassAction::RemoveAll;
}
Ordering::Less => StmtKind::Left(l - r),
Ordering::Greater => StmtKind::Right(r - l),
};
WindowPassAction::Merge(new)
}
(StmtKind::Add(offset_a, r), StmtKind::Sub(offset_b, l))
| (StmtKind::Sub(offset_a, l), StmtKind::Add(offset_b, r))
if offset_a == offset_b =>
{
let new = match r.cmp(l) {
Ordering::Equal => return WindowPassAction::RemoveAll,
Ordering::Less => StmtKind::Sub(*offset_a, l - r),
Ordering::Greater => StmtKind::Add(*offset_a, r - l),
};
WindowPassAction::Merge(new)
}
_ => WindowPassAction::None,
}
})
}
/// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9, 5)`
#[tracing::instrument(skip(ir))]
fn pass_add_sub_offset(ir: &mut Hir<'_>) {
pass_add_sub_offset_inner(ir)
}
fn pass_add_sub_offset_inner(ir: &mut Hir<'_>) {
window_pass(ir, pass_add_sub_offset_inner, |[a, b, c]| {
match (a.kind(), b.kind(), c.kind()) {
(StmtKind::Right(r), StmtKind::Add(0, n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::Add(i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Left(l), StmtKind::Add(0, n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::Add(-i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Right(r), StmtKind::Sub(0, n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::Sub(i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Left(l), StmtKind::Sub(0, n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::Sub(-i32::try_from(*r).unwrap(), *n))
}
_ => WindowPassAction::None,
}
})
}
/// pass that replaces `Loop([Sub(1) AddOffset(o, 1)])` with `MoveAddTo(o)`
#[tracing::instrument(skip(ir))]
fn pass_move_add_to(ir: &mut Hir<'_>) {
pass_move_add_to_inner(ir)
}
fn pass_move_add_to_inner(ir: &mut Hir<'_>) {
for stmt in &mut ir.stmts {
if let Stmt {
kind: StmtKind::Loop(body),
span,
} = stmt
{
if let [Stmt {
kind: StmtKind::Sub(0, 1),
..
}, Stmt {
kind: StmtKind::Add(offset, 1),
..
}]
| [Stmt {
kind: StmtKind::Add(offset, 1),
..
}, Stmt {
kind: StmtKind::Sub(0, 1),
..
}] = body.stmts.as_slice()
{
trace!(?span, ?offset, "Replacing Statement with MoveAddTo");
*stmt = Stmt::new(StmtKind::MoveAddTo { offset: *offset }, *span);
} else {
pass_move_add_to_inner(body);
}
}
}
}
#[tracing::instrument(skip(ir))]
fn pass_unroll_loops(ir: &mut Hir<'_>) {
let alloc = Bump::new();
pass_unroll_loops_inner(&alloc, ir);
}
fn pass_unroll_loops_inner(alloc: &Bump, ir: &mut Hir<'_>) {
window_pass(ir, pass_unroll_loops, |[a, b]| {
if let (StmtKind::SetN(n), StmtKind::Loop(body)) = (a.kind(), b.kind()) {
let mut stmts_vec = BumpVec::new_in(alloc);
let stmts = std::iter::repeat(body.stmts.iter())
.take(usize::from(*n))
.flatten()
.cloned();
stmts_vec.extend(stmts);
WindowPassAction::MergeMany(stmts_vec)
} else {
WindowPassAction::None
}
})
}
enum WindowPassAction<'hir, 'pass> {
None,
Merge(StmtKind<'hir>),
MergeMany(BumpVec<'pass, Stmt<'hir>>),
RemoveAll,
}
fn window_pass<'hir, 'pass, P, F, const N: usize>(ir: &mut Hir<'hir>, pass_recur: P, action: F)
where
P: Fn(&mut Hir<'hir>),
F: Fn([&Stmt<'hir>; N]) -> WindowPassAction<'hir, 'pass>,
{
assert!(N > 0);
let stmts = &mut ir.stmts;
let mut i = 0;
while i < stmts.len() {
let a = &mut stmts[i];
if let StmtKind::Loop(body) = &mut a.kind {
pass_recur(body);
}
if i + N > stmts.len() {
break; // there aren't N elements left
}
let mut elements = stmts[i..][..N].iter();
let elements = [(); N].map(|()| elements.next().unwrap());
let merged_span = elements[0].span.merge(elements.last().unwrap().span);
let result = action(elements);
match result {
WindowPassAction::None => {
// only increment i if we haven't removed anything
i += 1;
}
WindowPassAction::RemoveAll => {
trace!(?elements, "Removing all statements");
for _ in 0..N {
stmts.remove(i);
}
}
WindowPassAction::Merge(new) => {
trace!(?elements, ?new, "Merging statements");
for _ in 1..N {
stmts.remove(i);
}
stmts[i] = Stmt::new(new, merged_span);
}
WindowPassAction::MergeMany(new) => {
trace!(?elements, ?new, "Merging many");
for _ in 0..N {
stmts.remove(i);
}
for stmt in new.into_iter().rev() {
stmts.insert(i, stmt);
}
}
}
}
}

View file

@ -1,185 +0,0 @@
#![feature(allocator_api, let_else)]
#![feature(nonzero_ops)]
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(rust_2018_idioms)]
use std::{
fmt::Display,
io::{Read, Write},
path::PathBuf,
str::FromStr,
};
use bumpalo::Bump;
use owo_colors::OwoColorize;
use crate::parse::ParseError;
pub mod hir;
pub mod lir;
mod mir;
pub mod parse;
#[derive(clap::Parser, Default)]
#[clap(author, about)]
pub struct Args {
/// Print colored source code depending on how often it was run.
/// Makes the interpreter ~30% slower.
#[clap(short, long)]
pub profile: bool,
/// Dump the IR info (ast, hir, mir, lir)
#[clap(long)]
pub dump: Option<DumpKind>,
/// Use experimental mid-level IR
#[clap(long)]
pub mir: bool,
/// The file to run
pub file: PathBuf,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DumpKind {
Ast,
Hir,
Mir,
Lir,
}
impl FromStr for DumpKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ast" => Ok(Self::Ast),
"hir" => Ok(Self::Hir),
"mir" => Ok(Self::Mir),
"lir" => Ok(Self::Lir),
other => Err(format!("Invalid IR level: '{other}'")),
}
}
}
type BumpVec<'a, T> = Vec<T, &'a Bump>;
pub enum UseProfile {
Yes,
No,
}
pub fn run<R, W>(src: &str, stdout: W, stdin: R, config: &Args) -> Result<(), ParseError>
where
W: Write,
R: Read,
{
let ast_alloc = Bump::new();
let parsed = parse::parse(&ast_alloc, src.bytes().enumerate())?;
if let Some(DumpKind::Ast) = config.dump {
println!("{parsed:#?}");
return Ok(());
}
let hir_alloc = Bump::new();
let optimized_hir = hir::optimized_hir(&hir_alloc, &parsed);
if let Some(DumpKind::Hir) = config.dump {
println!("{}", dbg_pls::color(&optimized_hir));
return Ok(());
}
drop(parsed);
drop(ast_alloc);
if config.dump == Some(DumpKind::Mir) || config.mir {
let mir_alloc = Bump::new();
let mir = mir::optimized_mir(&mir_alloc, &optimized_hir);
if config.dump == Some(DumpKind::Mir) {
println!("{mir:#?}");
}
}
let cg_alloc = Bump::new();
let lir = lir::generate(&cg_alloc, &optimized_hir);
if let Some(DumpKind::Lir) = config.dump {
println!("{lir:#?}");
return Ok(());
}
drop(optimized_hir);
drop(hir_alloc);
match config.profile {
true => {
let mut code_profile_count = vec![0; lir.debug().len()];
lir::interpreter::run(&lir, stdout, stdin, |ip| unsafe {
*code_profile_count.get_unchecked_mut(ip) += 1;
});
let mut src_profile_count = vec![0u64; src.len()];
for (stmt_span, stmt_count) in lir.debug().iter().zip(&code_profile_count) {
for i in &mut src_profile_count[stmt_span.start()..stmt_span.end()] {
*i += stmt_count;
}
}
let max = src_profile_count.iter().max().copied().unwrap_or(0);
println!("\n\n---------------- Profile ----------------");
for (char, value) in src.bytes().zip(src_profile_count) {
print!("{}", color_by_profile(char as char, value, max));
}
}
false => {
lir::interpreter::run(&lir, stdout, stdin, |_| {});
}
}
Ok(())
}
fn color_by_profile(char: char, value: u64, max: u64) -> impl Display {
let max = max as f64;
let value = value as f64;
let ratio = value / max;
let logged = -ratio.log10();
let logged = (logged * 100.) as u64;
match logged {
0..=15 => char.bright_red().to_string(),
16..=70 => char.yellow().to_string(),
71..=300 => char.green().to_string(),
_ => char.default_color().to_string(),
}
}
#[cfg(test)]
mod tests {
use crate::Args;
#[test]
fn fizzbuzz() {
let str = include_str!("../benches/fizzbuzz.bf");
let mut stdout = Vec::new();
let stdin = [];
super::run(str, &mut stdout, stdin.as_slice(), &Args::default()).unwrap();
insta::assert_debug_snapshot!(String::from_utf8(stdout));
}
#[test]
fn mandelbrot() {
let str = include_str!("../benches/mandelbrot.bf");
let mut stdout = Vec::new();
let stdin = [];
super::run(str, &mut stdout, stdin.as_slice(), &Args::default()).unwrap();
insta::assert_debug_snapshot!(String::from_utf8(stdout));
}
}

View file

@ -1,139 +0,0 @@
use std::{
io::{Read, Write},
num::Wrapping,
};
use crate::lir::{Lir, Stmt};
const MEM_SIZE: usize = 32_000;
type Memory = [Wrapping<u8>; MEM_SIZE];
// `repr(C)` to make sure rustc never reorders the fields weirdly
// maybe useless, but seems to give tiny wins
#[repr(C)]
struct Interpreter<'lir, W, R, P> {
code: &'lir Lir<'lir>,
profile_collector: P,
ip: usize,
ptr: usize,
mem: Memory,
stdout: W,
stdin: R,
}
pub fn run<W, R, P>(code: &Lir<'_>, stdout: W, stdin: R, profile_collector: P)
where
W: Write,
R: Read,
P: FnMut(usize),
{
let mut interpreter = Interpreter {
code,
ip: 0,
ptr: 0,
stdout,
stdin,
mem: [Wrapping(0u8); MEM_SIZE],
profile_collector,
};
// SAFETY: `Lir` can only be produced by the `crate::lir` module, which is trusted to not
// produce out of bounds jumps and put the `End` at the end
unsafe {
interpreter.execute();
}
}
impl<'c, W: Write, R: Read, P> Interpreter<'c, W, R, P>
where
P: FnMut(usize),
{
unsafe fn execute(&mut self) {
let stmts = self.code.stmts();
loop {
// SAFETY: If the code ends with an `End` and there are no out of bounds jumps,
// `self.ip` will never be out of bounds
// Removing this bounds check speeds up execution by about 40%
debug_assert!(self.ip < stmts.len());
let instr = unsafe { *stmts.get_unchecked(self.ip) };
self.ip += 1;
match instr {
Stmt::Add(n) => {
*self.elem_mut() += n;
}
Stmt::Sub(n) => {
*self.elem_mut() -= n;
}
Stmt::AddOffset { offset, n } => *self.elem_mut_offset(offset) += n,
Stmt::SubOffset { offset, n } => *self.elem_mut_offset(offset) -= n,
Stmt::MoveAddTo { offset } => {
let value = self.elem();
*self.elem_mut() = Wrapping(0);
*self.elem_mut_offset(offset) += value;
}
Stmt::Right(n) => {
self.ptr += n as usize;
if self.ptr >= MEM_SIZE {
self.ptr = 0;
}
}
Stmt::Left(n) => {
if self.ptr < n as usize {
let diff = n as usize - self.ptr;
self.ptr = MEM_SIZE - 1 - diff;
} else {
self.ptr -= n as usize;
}
}
Stmt::Out => {
let char = self.elem() as char;
write!(self.stdout, "{char}").unwrap();
self.stdout.flush().unwrap();
}
Stmt::In => {
let mut buf = [0; 1];
self.stdin.read_exact(&mut buf).unwrap();
*self.elem_mut() = Wrapping(buf[0]);
}
Stmt::SetN(n) => {
*self.elem_mut() = Wrapping(n);
}
Stmt::JmpIfZero(pos) => {
if self.elem() == 0 {
self.ip = pos as usize;
}
}
Stmt::JmpIfNonZero(pos) => {
if self.elem() != 0 {
self.ip = pos as usize;
}
}
Stmt::End => break,
}
// this should be a no-op if `profile_collector` is does nothing
(self.profile_collector)(self.ip);
}
}
fn elem_mut_offset(&mut self, offset: i32) -> &mut Wrapping<u8> {
let ptr = self.ptr as isize;
let offset = offset as isize;
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut((ptr + offset) as usize) }
}
fn elem_mut(&mut self) -> &mut Wrapping<u8> {
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut(self.ptr) }
}
fn elem(&self) -> u8 {
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked(self.ptr).0 }
}
}

View file

@ -1,137 +0,0 @@
//! codegen to flat code
//!
//! ```bf
//! ++[-].
//! ```
//! compiles down to
//! ```text
//! Add | Add | JmpIfZero | Sub | JumpIfNotZero | Out | End
//! | ^ | ^
//! +-------|-----------|---------|
//! +-----------+
//! ```
//!
//! technically, the `JumpIfNotZero` would be an unconditional Jmp to the `JmpIfZero`, but that's
//! a needless indirection.
//!
//! this module must not produce out of bounds jumps and always put the `End` instruction at the
//! end
pub mod interpreter;
use std::fmt::{Debug, Formatter};
use bumpalo::Bump;
use crate::{
hir::{Hir, Stmt as HirStmt, StmtKind as HirStmtKind},
parse::Span,
BumpVec,
};
#[derive(Debug, Clone, Copy)]
pub enum Stmt {
Add(u8),
Sub(u8),
AddOffset { offset: i32, n: u8 },
SubOffset { offset: i32, n: u8 },
MoveAddTo { offset: i32 },
Right(u32),
Left(u32),
Out,
In,
SetN(u8),
JmpIfZero(u32),
JmpIfNonZero(u32),
End,
}
const _: [(); 8] = [(); std::mem::size_of::<Stmt>()];
#[derive(Clone)]
pub struct Lir<'lir> {
stmts: BumpVec<'lir, Stmt>,
debug: BumpVec<'lir, Span>,
}
impl Debug for Lir<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.stmts.fmt(f)
}
}
impl Lir<'_> {
pub fn stmts(&self) -> &[Stmt] {
&self.stmts
}
pub fn debug(&self) -> &[Span] {
&self.debug
}
}
pub fn generate<'lir>(alloc: &'lir Bump, ir: &Hir<'_>) -> Lir<'lir> {
let stmts = Vec::new_in(alloc);
let debug = Vec::new_in(alloc);
let mut lir = Lir { stmts, debug };
hir_to_lir(&mut lir, &ir.stmts);
lir.stmts.push(Stmt::End);
lir.debug.push(Span::default());
assert_eq!(lir.stmts.len(), lir.debug.len());
lir
}
fn hir_to_lir<'lir>(lir: &mut Lir<'lir>, ir: &[HirStmt<'_>]) {
for ir_stmt in ir {
hir_stmt_to_lir_stmt(lir, ir_stmt);
}
debug_assert_eq!(lir.stmts.len(), lir.debug.len());
}
fn hir_stmt_to_lir_stmt<'lir>(lir: &mut Lir<'lir>, ir_stmt: &HirStmt<'_>) {
let stmt = match &ir_stmt.kind {
HirStmtKind::Add(0, n) => Stmt::Add(*n),
HirStmtKind::Sub(0, n) => Stmt::Sub(*n),
HirStmtKind::Add(offset, n) => Stmt::AddOffset {
offset: *offset,
n: *n,
},
HirStmtKind::Sub(offset, n) => Stmt::SubOffset {
offset: *offset,
n: *n,
},
HirStmtKind::MoveAddTo { offset } => Stmt::MoveAddTo { offset: *offset },
HirStmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
HirStmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
HirStmtKind::Out => Stmt::Out,
HirStmtKind::In => Stmt::In,
HirStmtKind::SetN(n) => Stmt::SetN(*n),
HirStmtKind::Loop(instr) => {
let skip_jmp_idx = lir.stmts.len();
lir.stmts.push(Stmt::JmpIfZero(0)); // placeholder
lir.debug.push(ir_stmt.span);
// compile the loop body now
hir_to_lir(lir, &instr.stmts);
// if the loop body is empty, we jmp to ourselves, which is an infinite loop - as expected
let first_loop_body_idx = skip_jmp_idx + 1;
lir.stmts
.push(Stmt::JmpIfNonZero(first_loop_body_idx.try_into().unwrap()));
lir.debug.push(ir_stmt.span);
// there will always at least be an `End` instruction after the loop
let after_loop_idx = lir.stmts.len();
// fix the placeholder with the actual index
lir.stmts[skip_jmp_idx] = Stmt::JmpIfZero(after_loop_idx.try_into().unwrap());
return;
}
};
lir.stmts.push(stmt);
lir.debug.push(ir_stmt.span);
}

View file

@ -1,31 +0,0 @@
#![feature(allocator_api, let_else)]
#![warn(rust_2018_idioms)]
use std::{fs, io, process};
use brainfuck::Args;
use clap::Parser;
fn main() {
let stdout = io::stdout();
let stdout = stdout.lock();
let stdin = io::stdin();
let stdin = stdin.lock();
let args = Args::parse();
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
.without_time()
.init();
let src = fs::read_to_string(&args.file).unwrap_or_else(|err| {
eprintln!("error: Failed to read file: {err}");
process::exit(1);
});
brainfuck::run(&src, stdout, stdin, &args).unwrap_or_else(|_| {
eprintln!("error: Failed to parse brainfuck code");
process::exit(1);
});
}

View file

@ -1,120 +0,0 @@
//! an experimental MIR (mid-level-ir)
//!
//! The MIR consists of two parts. First, there are instructions (`Stmt`). These instructions
//! can be seen as an extended version of the default brainfuck instruction set `+-<>,.[]`.
//! These instructions modify the classic tape. What MIR does is that it attaches an abstract
//! `MemoryState` to *each* statement. This state contains all facts known about the state of the
//! tape at the point of execution of the statement.
//!
//! For example, for the code `++.`, the `MemoryState` for the `.` instruction contains a single
//! fact: "The current cell was written to, by the instruction before and with the value 2". MIR
//! tracks as much of the reads/writes to determine their dependencies and eliminate as many
//! of them as possible.
//!
//! Note that MIR is always pessimized, so if it can't determine for sure that something is true,
//! it will not act on it.
#![allow(dead_code)]
mod opts;
mod state;
use std::fmt::{Debug, Formatter};
use bumpalo::Bump;
use crate::{
hir::{Hir, StmtKind as HirStmtKind},
mir::state::{MemoryState, Store},
parse::Span,
BumpVec,
};
#[derive(Debug, Clone)]
pub struct Mir<'mir> {
stmts: BumpVec<'mir, Stmt<'mir>>,
}
#[derive(Clone)]
struct Stmt<'mir> {
kind: StmtKind<'mir>,
state: MemoryState<'mir>,
span: Span,
}
impl Debug for Stmt<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Stmt")
.field("kind", &self.kind)
.field("state", &self.state)
.finish()
}
}
type Offset = i32;
#[derive(Debug, Clone)]
enum StmtKind<'mir> {
/// Add or sub, the value has the valid range -255..=255
AddSub {
offset: Offset,
n: i16,
store: Store,
},
/// Sets the current cell to 0 and adds that value of the cell to another cell at `offset`
MoveAddTo {
offset: Offset,
store_set_null: Store,
store_move: Store,
},
/// Left or Right pointer move (`<>`)
PointerMove(Offset),
Loop(Mir<'mir>),
Out,
In(Store),
SetN(u8, Store),
}
#[tracing::instrument(skip(alloc, hir))]
pub fn optimized_mir<'mir>(alloc: &'mir Bump, hir: &Hir<'_>) -> Mir<'mir> {
let mut mir = hir_to_mir(alloc, hir);
opts::passes(alloc, &mut mir);
mir
}
/// compiles hir down to a minimal mir
fn hir_to_mir<'mir>(alloc: &'mir Bump, hir: &Hir<'_>) -> Mir<'mir> {
let mut stmts = Vec::new_in(alloc);
let iter = hir.stmts.iter().map(|hir_stmt| {
let kind = match *hir_stmt.kind() {
HirStmtKind::Add(offset, n) => StmtKind::AddSub {
offset,
n: i16::from(n),
store: Store::dead(),
},
HirStmtKind::Sub(offset, n) => StmtKind::AddSub {
offset,
n: -i16::from(n),
store: Store::dead(),
},
HirStmtKind::MoveAddTo { offset } => StmtKind::MoveAddTo {
offset,
store_set_null: Store::dead(),
store_move: Store::dead(),
},
HirStmtKind::Right(n) => StmtKind::PointerMove(i32::try_from(n).unwrap()),
HirStmtKind::Left(n) => StmtKind::PointerMove(-i32::try_from(n).unwrap()),
HirStmtKind::Loop(ref body) => StmtKind::Loop(hir_to_mir(alloc, body)),
HirStmtKind::Out => StmtKind::Out,
HirStmtKind::In => StmtKind::In(Store::dead()),
HirStmtKind::SetN(n) => StmtKind::SetN(n, Store::dead()),
};
Stmt {
kind,
span: hir_stmt.span,
state: MemoryState::empty(alloc),
}
});
stmts.extend(iter);
Mir { stmts }
}

View file

@ -1,215 +0,0 @@
use std::collections::{hash_map::Entry, HashMap};
use bumpalo::Bump;
use tracing::info;
use crate::mir::{
state::{CellState, MemoryState, MemoryStateChange, Store},
Mir, Offset, StmtKind,
};
/// this pass fills out as much state info for all statements as possible
#[tracing::instrument(skip(alloc, mir))]
pub fn passes<'mir>(alloc: &'mir Bump, mir: &mut Mir<'mir>) {
pass_fill_state_info(alloc, mir);
pass_const_propagation(mir);
pass_dead_store_elimination(mir);
}
/// this pass fills out as much state info for all statements as possible
#[tracing::instrument(skip(alloc, mir))]
pub fn pass_fill_state_info<'mir>(alloc: &'mir Bump, mir: &mut Mir<'mir>) {
let empty_state = MemoryState::empty(alloc);
pass_fill_state_info_inner(alloc, mir, empty_state);
}
// note: this whole thing is unsound because it doesn't consider that stores inside a loop
// could be loaded from after the loop
fn pass_fill_state_info_inner<'mir>(
alloc: &'mir Bump,
mir: &mut Mir<'mir>,
mut outer: MemoryState<'mir>,
) {
for stmt in &mut mir.stmts {
let state = match &mut stmt.kind {
StmtKind::AddSub { offset, n, store } => {
let prev_state = outer.state_for_offset(*offset);
let new_state = match prev_state {
CellState::WrittenToKnown(_, prev_n) => {
let n = i16::from(prev_n).wrapping_add(*n);
let n = u8::try_from(n).unwrap();
CellState::WrittenToKnown(store.clone(), n)
}
_ => CellState::WrittenToUnknown(store.clone()),
};
MemoryState::single(
alloc,
outer,
MemoryStateChange::Change {
offset: *offset,
new_state,
},
)
}
StmtKind::MoveAddTo {
offset,
store_set_null,
store_move,
} => MemoryState::double(
alloc,
outer,
MemoryStateChange::Change {
offset: 0,
new_state: CellState::WrittenToKnown(store_set_null.clone(), 0),
},
MemoryStateChange::Change {
offset: *offset,
new_state: CellState::WrittenToUnknown(store_move.clone()),
},
),
StmtKind::PointerMove(n) => {
MemoryState::single(alloc, outer, MemoryStateChange::Move(*n))
}
StmtKind::Loop(body) => {
// TODO: we can get a lot smarter here and get huge benefits; we don't yet
pass_fill_state_info_inner(alloc, body, MemoryState::empty(alloc));
MemoryState::double(
alloc,
outer,
// forget all knowledge, the opaque loop might have touched it all
MemoryStateChange::Forget,
// we certainly know that the current cell is zero, since the loop exited
MemoryStateChange::Change {
offset: 0,
new_state: CellState::LoopNull,
},
)
}
StmtKind::Out => outer,
StmtKind::In(store) => MemoryState::single(
alloc,
outer,
MemoryStateChange::Change {
offset: 0,
new_state: CellState::WrittenToUnknown(store.clone()),
},
),
StmtKind::SetN(value, store) => MemoryState::single(
alloc,
outer,
MemoryStateChange::Change {
offset: 0,
new_state: CellState::WrittenToKnown(store.clone(), *value),
},
),
};
stmt.state = state.clone();
outer = state;
}
}
/// This pass eliminates dead stores. It should probably be run multiple times between other passes
/// for cleanup
#[tracing::instrument(skip(mir))]
fn pass_dead_store_elimination(mir: &mut Mir<'_>) {
pass_dead_store_elimination_mark_dead_stores(mir)
}
#[tracing::instrument(skip(mir))]
fn pass_dead_store_elimination_mark_dead_stores(mir: &Mir<'_>) {
fn mark_store(
potential_dead_stores: &mut HashMap<Offset, Store>,
offset: Offset,
store: &Store,
) {
match potential_dead_stores.entry(offset) {
Entry::Occupied(mut entry) => {
let old = entry.insert(store.clone());
if old.is_maybe_dead() {
// it's certainly dead
info!("We have a dead one!!!");
old.mark_dead();
} else {
// it's alive and well, drop it and keep it marked alive
drop(old);
}
}
Entry::Vacant(entry) => {
entry.insert(store.clone());
}
}
}
let mut potential_dead_stores = HashMap::new();
let mut current_offset = 0;
for stmt in &mir.stmts {
match &stmt.kind {
StmtKind::AddSub { store, offset, .. } => {
mark_store(&mut potential_dead_stores, current_offset + offset, store);
}
StmtKind::MoveAddTo {
offset,
store_move,
store_set_null,
} => {
mark_store(&mut potential_dead_stores, current_offset, store_set_null);
mark_store(
&mut potential_dead_stores,
current_offset + offset,
store_move,
);
}
StmtKind::PointerMove(offset) => {
current_offset += offset; // ???
}
StmtKind::Loop(body) => {
let store = potential_dead_stores.get(&current_offset);
if let Some(store) = store {
store.add_load();
}
pass_dead_store_elimination_mark_dead_stores(body);
}
StmtKind::Out => {
let store = potential_dead_stores.get(&current_offset);
if let Some(store) = store {
store.add_load();
}
}
StmtKind::In(store) | StmtKind::SetN(_, store) => {
mark_store(&mut potential_dead_stores, current_offset, store);
}
}
if stmt.state.has_forget_delta() {
// they might all have loads now
potential_dead_stores.values().for_each(Store::clobber);
}
info!(?potential_dead_stores, ?current_offset, "stores");
}
}
// test pass
#[tracing::instrument(skip(mir))]
fn pass_const_propagation(mir: &mut Mir<'_>) {
pass_const_propagation_inner(mir)
}
fn pass_const_propagation_inner(mir: &mut Mir<'_>) {
for stmt in &mut mir.stmts {
match &mut stmt.kind {
StmtKind::Out => {
let _state = stmt.state.state_for_offset(0);
// we could now insert a `SetN` before the `Out`, to mark the previous store
// as dead.
}
StmtKind::Loop(body) => {
let _state = stmt.state.state_for_offset(0);
// we could now insert a `SetN` before the `Loop`, to mark the previous store
// as dead.
pass_const_propagation_inner(body);
}
_ => {}
}
}
}

View file

@ -1,220 +0,0 @@
// todo: we're gonna leak `Rc`s here aren't we?
use std::{
cell::{Cell, RefCell},
fmt::{Debug, Formatter},
num::NonZeroU32,
rc::Rc,
};
use bumpalo::Bump;
use crate::{mir::Offset, BumpVec};
/// The known state of a cell in the MIR
#[derive(Debug, Clone)]
pub enum CellState {
/// The state of this cell is completely unknown and could be anything, for example after `,`
Unknown,
/// This cell is guaranteed to be `0` because a loop just terminated on it
LoopNull,
/// Some value was written to this cell classified by the `Store`, but we do not know the value
WrittenToUnknown(Store),
/// A known value was written to this cell
WrittenToKnown(Store, u8),
}
/// A change in the known state of the memory caused by a single instruction
#[derive(Debug, Clone)]
pub enum MemoryStateChange {
/// A cell value was changed to a new state.
Change {
offset: Offset,
new_state: CellState,
},
/// The pointer was moved. This affects the `offset` calculations from previous states.
Move(Offset),
/// Forget everything about the memory state. This currently happens after each loop, since
/// the loop is opaque and might clobber everything.
Forget,
/// Load a value from memory. This is not a direct change of the memory itself, but it does
/// change the state in that it marks the corresponding store, if any, as alive. Loads should
/// be eliminated whenever possible, to remove as many dead stores as possible.
Load { offset: Offset },
}
/// The known state of memory at a specific instance in the instruction sequence
#[derive(Clone)]
pub struct MemoryState<'mir>(Rc<RefCell<MemoryStateInner<'mir>>>);
impl<'mir> MemoryState<'mir> {
pub fn empty(alloc: &'mir Bump) -> Self {
Self::new(None, Vec::new_in(alloc))
}
pub fn single(
alloc: &'mir Bump,
prev: MemoryState<'mir>,
delta: MemoryStateChange,
) -> MemoryState<'mir> {
let mut deltas = Vec::new_in(alloc);
deltas.push(delta);
Self::new(Some(prev), deltas)
}
pub fn double(
alloc: &'mir Bump,
prev: MemoryState<'mir>,
delta1: MemoryStateChange,
delta2: MemoryStateChange,
) -> MemoryState<'mir> {
let mut deltas = Vec::new_in(alloc);
deltas.push(delta1);
deltas.push(delta2);
Self::new(Some(prev), deltas)
}
pub fn new(
prev: Option<MemoryState<'mir>>,
deltas: BumpVec<'mir, MemoryStateChange>,
) -> MemoryState<'mir> {
Self(Rc::new(RefCell::new(MemoryStateInner { prev, deltas })))
}
pub fn state_for_offset(&self, offset: Offset) -> CellState {
self.0.borrow().state_for_offset(offset)
}
pub fn has_forget_delta(&self) -> bool {
self.0
.borrow()
.deltas
.iter()
.any(|d| matches!(d, MemoryStateChange::Forget))
}
}
impl Debug for MemoryState<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0
.try_borrow()
.map(|s| MemoryStateInner::fmt(&*s, f))
.unwrap_or_else(|_| f.debug_struct("MemoryState").finish_non_exhaustive())
}
}
/// The known state of memory relative to the pointer
#[derive(Debug, Clone)]
struct MemoryStateInner<'mir> {
prev: Option<MemoryState<'mir>>,
deltas: BumpVec<'mir, MemoryStateChange>,
}
impl<'mir> MemoryStateInner<'mir> {
fn state_for_offset(&self, offset: Offset) -> CellState {
let mut offset = offset;
for delta in &self.deltas {
match delta {
MemoryStateChange::Change {
offset: write_offset,
new_state,
} if *write_offset == offset => return new_state.clone(),
MemoryStateChange::Move(change) => offset -= change,
// we may not access the forbidden knowledge
MemoryStateChange::Forget => return CellState::Unknown,
_ => {}
}
}
self.prev
.as_ref()
.map(|state| state.state_for_offset(offset))
.unwrap_or(CellState::Unknown)
}
}
/// The abstract representation of a store in memory. Corresponding loads can also hold
/// a reference to this to mark the store as alive
#[derive(Clone)]
pub struct Store(Rc<Cell<StoreInner>>);
impl Store {
pub fn dead() -> Self {
StoreKind::Dead.into()
}
pub fn id(&self) -> u64 {
self.inner().id
}
pub fn add_load(&self) {
let old = self.inner();
let kind = match old.kind {
StoreKind::Unknown => StoreKind::UsedAtLeast(NonZeroU32::new(1).unwrap()),
StoreKind::UsedExact(n) => StoreKind::UsedExact(n.checked_add(1).unwrap()),
StoreKind::UsedAtLeast(n) => StoreKind::UsedAtLeast(n.checked_add(1).unwrap()),
StoreKind::Dead => StoreKind::UsedExact(NonZeroU32::new(1).unwrap()),
};
self.0.set(StoreInner { id: old.id, kind })
}
pub fn is_maybe_dead(&self) -> bool {
matches!(self.inner().kind, StoreKind::Dead | StoreKind::Unknown)
}
pub fn mark_dead(&self) {
let old = self.inner();
self.0.set(StoreInner {
id: old.id,
kind: StoreKind::Dead,
})
}
pub fn clobber(&self) {
let old = self.inner();
let kind = match old.kind {
StoreKind::Unknown => StoreKind::Unknown,
StoreKind::UsedExact(n) => StoreKind::UsedAtLeast(n),
StoreKind::UsedAtLeast(n) => StoreKind::UsedAtLeast(n),
StoreKind::Dead => StoreKind::Unknown,
};
self.0.set(StoreInner { id: old.id, kind })
}
fn inner(&self) -> StoreInner {
self.0.get()
}
}
impl Debug for Store {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner().kind.fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
struct StoreInner {
id: u64,
kind: StoreKind,
}
#[derive(Debug, Clone, Copy)]
enum StoreKind {
/// No information is known about uses of the store, it has probably been clobbered
Unknown,
/// The exact amount of subsequent loads is known about the store, and it's this
UsedExact(NonZeroU32),
/// The exact amount of subsequent loads not known about this store, but it's at least this
UsedAtLeast(NonZeroU32),
/// The store is known to be dead
Dead,
}
impl From<StoreKind> for Store {
fn from(kind: StoreKind) -> Self {
Self(Rc::new(Cell::new(StoreInner {
id: rand::random(),
kind,
})))
}
}

View file

@ -1,176 +0,0 @@
use std::{
cmp,
fmt::{Debug, Formatter},
};
use bumpalo::Bump;
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub struct Span {
start: u32,
len: u32,
}
impl Span {
fn single(idx: usize) -> Self {
Self {
start: idx.try_into().unwrap(),
len: 1,
}
}
/// start..end
fn start_end(start: usize, end: usize) -> Span {
Self {
start: start.try_into().unwrap(),
len: (end - start).try_into().unwrap(),
}
}
// start..=end
fn start_end_incl(start: usize, end: usize) -> Span {
Self {
start: start.try_into().unwrap(),
len: (end - start + 1).try_into().unwrap(),
}
}
#[must_use]
pub fn until(&self, other: Self) -> Self {
Self {
start: self.start,
len: (other.start + other.len) - self.len,
}
}
#[must_use]
pub fn merge(&self, other: Self) -> Self {
Self::start_end(
cmp::min(self.start(), other.start()),
cmp::max(self.end(), other.end()),
)
}
pub fn start(&self) -> usize {
self.start.try_into().unwrap()
}
pub fn len(&self) -> usize {
self.len.try_into().unwrap()
}
/// ..end
pub fn end(&self) -> usize {
self.start() + self.len()
}
}
impl Debug for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&(self.start..(self.start + self.len)), f)
}
}
pub type Ast<'ast> = Vec<(Instr<'ast>, Span), &'ast Bump>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instr<'ast> {
Add,
Sub,
Right,
Left,
Out,
In,
Loop(Ast<'ast>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseError;
pub fn parse<I>(alloc: &Bump, mut src: I) -> Result<Ast<'_>, ParseError>
where
I: Iterator<Item = (usize, u8)>,
{
let mut instrs = Vec::new_in(alloc);
loop {
match src.next() {
Some((idx, b'+')) => instrs.push((Instr::Add, Span::single(idx))),
Some((idx, b'-')) => instrs.push((Instr::Sub, Span::single(idx))),
Some((idx, b'>')) => instrs.push((Instr::Right, Span::single(idx))),
Some((idx, b'<')) => instrs.push((Instr::Left, Span::single(idx))),
Some((idx, b'.')) => instrs.push((Instr::Out, Span::single(idx))),
Some((idx, b',')) => instrs.push((Instr::In, Span::single(idx))),
Some((idx, b'[')) => {
let (loop_instrs, span) = parse_loop(alloc, &mut src, 0, idx)?;
instrs.push((Instr::Loop(loop_instrs), span));
}
Some((_, b']')) => return Err(ParseError),
Some(_) => {} // comment
None => break,
}
}
Ok(instrs)
}
fn parse_loop<'ast, I>(
alloc: &'ast Bump,
src: &mut I,
depth: u16,
start_idx: usize,
) -> Result<(Ast<'ast>, Span), ParseError>
where
I: Iterator<Item = (usize, u8)>,
{
const MAX_DEPTH: u16 = 1000;
if depth > MAX_DEPTH {
return Err(ParseError);
}
let mut instrs = Vec::new_in(alloc);
let end_idx = loop {
match src.next() {
Some((idx, b'+')) => instrs.push((Instr::Add, Span::single(idx))),
Some((idx, b'-')) => instrs.push((Instr::Sub, Span::single(idx))),
Some((idx, b'>')) => instrs.push((Instr::Right, Span::single(idx))),
Some((idx, b'<')) => instrs.push((Instr::Left, Span::single(idx))),
Some((idx, b'.')) => instrs.push((Instr::Out, Span::single(idx))),
Some((idx, b',')) => instrs.push((Instr::In, Span::single(idx))),
Some((idx, b'[')) => {
let (loop_instrs, span) = parse_loop(alloc, src, depth + 1, idx)?;
instrs.push((Instr::Loop(loop_instrs), span));
}
Some((idx, b']')) => break idx,
Some(_) => {} // comment
None => return Err(ParseError),
}
};
Ok((instrs, Span::start_end_incl(start_idx, end_idx)))
}
#[cfg(test)]
mod tests {
use bumpalo::Bump;
#[test]
fn simple() {
let alloc = Bump::new();
let bf = ">+<++[-].";
let instrs = super::parse(&alloc, bf.bytes().enumerate());
insta::assert_debug_snapshot!(instrs);
}
#[test]
fn nested_loop() {
let alloc = Bump::new();
let bf = "+[-[-[-]]+>>>]";
let instrs = super::parse(&alloc, bf.bytes().enumerate());
insta::assert_debug_snapshot!(instrs);
}
}

View file

@ -1,61 +0,0 @@
---
source: src/parse.rs
expression: instrs
---
Ok(
[
(
Add,
0..1,
),
(
Loop(
[
(
Sub,
2..3,
),
(
Loop(
[
(
Sub,
4..5,
),
(
Loop(
[
(
Sub,
6..7,
),
],
),
5..8,
),
],
),
3..9,
),
(
Add,
9..10,
),
(
Right,
10..11,
),
(
Right,
11..12,
),
(
Right,
12..13,
),
],
),
1..14,
),
],
)

View file

@ -1,43 +0,0 @@
---
source: src/parse.rs
expression: instrs
---
Ok(
[
(
Right,
0..1,
),
(
Add,
1..2,
),
(
Left,
2..3,
),
(
Add,
3..4,
),
(
Add,
4..5,
),
(
Loop(
[
(
Sub,
6..7,
),
],
),
5..8,
),
(
Out,
8..9,
),
],
)

View file

@ -1,8 +0,0 @@
---
source: src/lib.rs
assertion_line: 43
expression: "String::from_utf8(stdout)"
---
Ok(
"1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\nBuzz\n",
)

View file

@ -1,7 +0,0 @@
---
source: src/lib.rs
expression: "String::from_utf8(stdout)"
---
Ok(
"AAAAAAAABBBBBBBBCCCCCCCCCCCCCCCCCCDDDDEFEEDDDCCCCCBBBBBBBBBBBBBBB\nAAAAAAABBBBBBCCCCCCCCCCCCCCCCCDDDDDDEEFIKGGGDDDDDCCCCBBBBBBBBBBBB\nAAAAAABBBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGHKPIGFEDDDDDCCCCCBBBBBBBBB\nAAAAABBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGPVT Q[HEEEEDDDCCCCCCBBBBBBB\nAAAABBCCCCCCCCCCCCCCCCDDDDDDDEEFFFGGHK HGFFEEEDDDCCCCCBBBBBB\nAAABBCCCCCCCCCCCCCCCDDDDDEEEFGK MJJ NR YS L HHGIJFDDCCCCCCBBBB\nAAABCCCCCCCCCCCCCDDDEEEEEEFFFHI MGEDDCCCCCCBBB\nAABCCCCCCCCCCCDDEEEEEEEEFFFGY Q MHGEEDCCCCCCCBB\nAACCCCCCDDDDDEEFLHGGHMHGGGHIR QLHEDDCCCCCCCB\nABCCDDDDDDEEEEFGIKU RLJJL IFEDDCCCCCCCB\nACDDDDDDEEEEEGGHOS QR JFEDDDCCCCCCC\nADDDDDEFFFGGHKOPS GEEDDDCCCCCCC\nA PJGFEEDDDCCCCCCC\nADDDDDEFFFGGHKOPS GEEDDDCCCCCCC\nACDDDDDDEEEEEGGHOS QR JFEDDDCCCCCCC\nABCCDDDDDDEEEEFGIKU RLJJL IFEDDCCCCCCCB\nAACCCCCCDDDDDEEFLHGGHMHGGGHIR QLHEDDCCCCCCCB\nAABCCCCCCCCCCCDDEEEEEEEEFFFGY Q MHGEEDCCCCCCCBB\nAAABCCCCCCCCCCCCCDDDEEEEEEFFFHI MGEDDCCCCCCBBB\nAAABBCCCCCCCCCCCCCCCDDDDDEEEFGK MJJ NR YS L HHGIJFDDCCCCCCBBBB\nAAAABBCCCCCCCCCCCCCCCCDDDDDDDEEFFFGGHK HGFFEEEDDDCCCCCBBBBBB\nAAAAABBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGPVT Q[HEEEEDDDCCCCCCBBBBBBB\nAAAAAABBBBCCCCCCCCCCCCCCCCCDDDDDDDEEEFGHKPIGFEDDDDDCCCCCBBBBBBBBB\nAAAAAAABBBBBBCCCCCCCCCCCCCCCCCDDDDDDEEFIKGGGDDDDDCCCCBBBBBBBBBBBB\n",
)

View file

@ -1 +0,0 @@
+++++>[-]+++[<.>]