Commits

johannes committed 7e0bb35

Initial revision

Comments (0)

Files changed (7)

+CXXFLAGS=-I/opt/local/include -L/opt/local/lib -llua -ldl
+
+quiz: slnudata.c slnunico.c quiz.cpp
+	$(CXX) $(CXXFLAGS) slnudata.c slnunico.c quiz.cpp -o $@
+#include <iostream>
+
+extern "C" {
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+LUALIB_API int luaopen_unicode (lua_State *L);
+}
+
+using namespace std;
+
+class ExcecutionError {};
+
+void run(lua_State *L, const char *filename)
+{
+	int res = luaL_dofile(L, filename);
+	if (res != 0)
+	{
+		cout << "Running program failed." << endl;
+		cout << lua_tostring(L, -1) << endl;
+		throw ExcecutionError();
+	}
+}
+
+int main()
+{
+	lua_State *L = lua_open();
+	try
+	{
+		luaL_openlibs(L);
+		luaopen_unicode(L);
+		run(L, "romanize.lua");
+		run(L, "quiz.lua");
+	}
+	catch (ExcecutionError)
+	{
+	}
+	lua_close(L);
+}
+
+--
+-- Japanese romanization quiz
+--
+-- Johannes Hoff, October 2010
+-- johshoff@gmail.com
+--
+
+-- Use awesome unicode library from http://luaforge.net/projects/sln/
+local utf8 = unicode.utf8
+
+words = {}
+words["はし"]         = "chopsticks"
+words["しょうゆ"]     = "soy oil"
+words["しょうちゅう"] = "sweet potato liquor"
+words["オクラ"]       = "okura"
+words["ゴーヤー"]     = "bitter melon"
+words["はじめまして"] = "nice to meet you"
+words["おみず"]       = "water"
+words["すみません"]   = "excuse me/sorry"
+words["ごめんなさい"] = "sorry"
+words["でんしゃ"]     = "train"
+words["えき"]         = "station"
+words["きっぷ"]       = "ticket"
+words["いくら"]       = "how much"
+words["ひと"]         = "person"
+words["あさ"]         = "morning"
+words["よる"]         = "evening"
+words["たかい"]       = "expensive"
+words["やすい"]       = "cheap"
+words["こうえん"]     = "park"
+words["とおい"]       = "far"
+words["おいしい"]     = "tasty"
+words["あたたかい"]   = "warm"
+words["さむい"]       = "cold"
+words["あかるい"]     = "bright"
+words["くらい"]       = "dark"
+words["ひゃく"]       = "one hundred"
+words["せん"]         = "one thousand"
+words["まん"]         = "ten thousand"
+words["あき"]         = "fall"
+words["ふゆ"]         = "winter"
+words["はる"]         = "spring"
+words["なつ"]         = "summer"
+--words[""]         = ""
+words["ありがとうございます"] = "thank you"
+words["おはようございます"]   = "good morning"
+
+for hiragana,english in pairs(words) do
+	print(hiragana .. " -> " .. romanize(hiragana) .. " (" .. english .. ")")
+end
+
+for hiragana,english in pairs(words) do
+	io.write(hiragana .. ": ")
+	local answer = io.read()
+	if answer ~= romanize(hiragana) then
+		print("CORRECT ANSWER: " .. romanize(hiragana))
+	end
+	print("(" .. english .. ")")
+end
+
+--
+-- Small utility to romanize hiragana and katakana string
+-- e.g. romanize("ありがとう") == "arigatou"
+--
+-- Johannes Hoff, October 2010
+-- johshoff@gmail.com
+--
+
+local utf8 = unicode.utf8
+
+-- based on http://en.wikipedia.org/wiki/Hiragana
+--      and http://en.wikipedia.org/wiki/Katakana
+-- heavily vimified
+romaji = {}
+romaji["あ"]	= "a"
+romaji["い"]	= "i"
+romaji["う"]	= "u"
+romaji["え"]	= "e"
+romaji["お"]	= "o"
+romaji["か"]	= "ka"
+romaji["き"]	= "ki"
+romaji["く"]	= "ku"
+romaji["け"]	= "ke"
+romaji["こ"]	= "ko"
+romaji["くゎ"]	= "kwa"
+romaji["きゃ"]	= "kya"
+romaji["きゅ"]	= "kyu"
+romaji["きょ"]	= "kyo"
+romaji["さ"]	= "sa"
+romaji["し"]	= "shi"
+romaji["す"]	= "su"
+romaji["せ"]	= "se"
+romaji["そ"]	= "so"
+romaji["しゃ"]	= "sha"
+romaji["しゅ"]	= "shu"
+romaji["しょ"]	= "sho"
+romaji["た"]	= "ta"
+romaji["ち"]	= "chi"
+romaji["つ"]	= "tsu"
+romaji["て"]	= "te"
+romaji["と"]	= "to"
+romaji["ちゃ"]	= "cha"
+romaji["ちゅ"]	= "chu"
+romaji["ちょ"]	= "cho"
+romaji["な"]	= "na"
+romaji["に"]	= "ni"
+romaji["ぬ"]	= "nu"
+romaji["ね"]	= "ne"
+romaji["の"]	= "no"
+romaji["にゃ"]	= "nya"
+romaji["にゅ"]	= "nyu"
+romaji["にょ"]	= "nyo"
+romaji["は"]	= "ha"
+romaji["ひ"]	= "hi"
+romaji["ふ"]	= "fu"
+romaji["へ"]	= "he"
+romaji["ほ"]	= "ho"
+romaji["ひゃ"]	= "hya"
+romaji["ひゅ"]	= "hyu"
+romaji["ひょ"]	= "hyo"
+romaji["ま"]	= "ma"
+romaji["み"]	= "mi"
+romaji["む"]	= "mu"
+romaji["め"]	= "me"
+romaji["も"]	= "mo"
+romaji["みゃ"]	= "mya"
+romaji["みゅ"]	= "myu"
+romaji["みょ"]	= "myo"
+romaji["や"]	= "ya"
+romaji["ゆ"]	= "yu"
+romaji["よ"]	= "yo"
+romaji["ら"]	= "ra"
+romaji["り"]	= "ri"
+romaji["る"]	= "ru"
+romaji["れ"]	= "re"
+romaji["ろ"]	= "ro"
+romaji["りゃ"]	= "rya"
+romaji["りゅ"]	= "ryu"
+romaji["りょ"]	= "ryo"
+romaji["わ"]	= "wa"
+romaji["ゐ"]	= "i"
+romaji["ゑ"]	= "e"
+romaji["を"]	= "wo"
+romaji["ん"]	= "n"
+romaji["が"]	= "ga"
+romaji["ぎ"]	= "gi"
+romaji["ぐ"]	= "gu"
+romaji["げ"]	= "ge"
+romaji["ご"]	= "go"
+romaji["ぐゎ"]	= "gwa"
+romaji["ぎゃ"]	= "gya"
+romaji["ぎゅ"]	= "gyu"
+romaji["ぎょ"]	= "gyo"
+romaji["ざ"]	= "za"
+romaji["じ"]	= "ji"
+romaji["ず"]	= "zu"
+romaji["ぜ"]	= "ze"
+romaji["ぞ"]	= "zo"
+romaji["じゃ"]	= "ja"
+romaji["じゅ"]	= "ju"
+romaji["じょ"]	= "jo"
+romaji["だ"]	= "da"
+romaji["ぢ"]	= "(ji)"
+romaji["づ"]	= "(zu)"
+romaji["で"]	= "de"
+romaji["ど"]	= "do"
+romaji["ぢゃ"]	= "(ja)"
+romaji["ぢゅ"]	= "(ju)"
+romaji["ぢょ"]	= "(jo)"
+romaji["ば"]	= "ba"
+romaji["び"]	= "bi"
+romaji["ぶ"]	= "bu"
+romaji["べ"]	= "be"
+romaji["ぼ"]	= "bo"
+romaji["びゃ"]	= "bya"
+romaji["びゅ"]	= "byu"
+romaji["びょ"]	= "byo"
+romaji["ぱ"]	= "pa"
+romaji["ぴ"]	= "pi"
+romaji["ぷ"]	= "pu"
+romaji["ぺ"]	= "pe"
+romaji["ぽ"]	= "po"
+romaji["ぴゃ"]	= "pya"
+romaji["ぴゅ"]	= "pyu"
+romaji["ぴょ"]	= "pyo"
+romaji["ゔ"]	= "vu"
+
+romaji["ア"]	= "a"
+romaji["イ"]	= "i"
+romaji["ウ"]	= "u"
+romaji["エ"]	= "e"
+romaji["オ"]	= "o"
+romaji["カ"]	= "ka"
+romaji["キ"]	= "ki"
+romaji["ク"]	= "ku"
+romaji["ケ"]	= "ke"
+romaji["コ"]	= "ko"
+romaji["キャ"]	= "kya"
+romaji["キュ"]	= "kyu"
+romaji["キョ"]	= "kyo"
+romaji["サ"]	= "sa"
+romaji["シ"]	= "shi"
+romaji["ス"]	= "su"
+romaji["セ"]	= "se"
+romaji["ソ"]	= "so"
+romaji["シャ"]	= "sha"
+romaji["シュ"]	= "shu"
+romaji["ショ"]	= "sho"
+romaji["タ"]	= "ta"
+romaji["チ"]	= "chi"
+romaji["ツ"]	= "tsu"
+romaji["テ"]	= "te"
+romaji["ト"]	= "to"
+romaji["チャ"]	= "cha"
+romaji["チュ"]	= "chu"
+romaji["チョ"]	= "cho"
+romaji["ナ"]	= "na"
+romaji["ニ"]	= "ni"
+romaji["ヌ"]	= "nu"
+romaji["ネ"]	= "ne"
+romaji["ノ"]	= "no"
+romaji["ニャ"]	= "nya"
+romaji["ニュ"]	= "nyu"
+romaji["ニョ"]	= "nyo"
+romaji["ハ"]	= "ha"
+romaji["ヒ"]	= "hi"
+romaji["フ"]	= "fu"
+romaji["ヘ"]	= "he"
+romaji["ホ"]	= "ho"
+romaji["ヒャ"]	= "hya"
+romaji["ヒュ"]	= "hyu"
+romaji["ヒョ"]	= "hyo"
+romaji["マ"]	= "ma"
+romaji["ミ"]	= "mi"
+romaji["ム"]	= "mu"
+romaji["メ"]	= "me"
+romaji["モ"]	= "mo"
+romaji["ミャ"]	= "mya"
+romaji["ミュ"]	= "myu"
+romaji["ミョ"]	= "myo"
+romaji["ヤ"]	= "ya"
+romaji["ユ"]	= "yu"
+romaji["ヨ"]	= "yo"
+romaji["ラ"]	= "ra"
+romaji["リ"]	= "ri"
+romaji["ル"]	= "ru"
+romaji["レ"]	= "re"
+romaji["ロ"]	= "ro"
+romaji["リャ"]	= "rya"
+romaji["リュ"]	= "ryu"
+romaji["リョ"]	= "ryo"
+romaji["ワ"]	= "wa"
+romaji["ヰ"]	= "i"
+romaji["ヱ"]	= "e"
+romaji["ヲ"]	= "wo"
+romaji["ガ"]	= "ga"
+romaji["ギ"]	= "gi"
+romaji["グ"]	= "gu"
+romaji["ゲ"]	= "ge"
+romaji["ゴ"]	= "go"
+romaji["ギャ"]	= "gya"
+romaji["ギュ"]	= "gyu"
+romaji["ギョ"]	= "gyo"
+romaji["ザ"]	= "za"
+romaji["ジ"]	= "ji"
+romaji["ズ"]	= "zu"
+romaji["ゼ"]	= "ze"
+romaji["ゾ"]	= "zo"
+romaji["ジャ"]	= "ja"
+romaji["ジュ"]	= "ju"
+romaji["ジョ"]	= "jo"
+romaji["ダ"]	= "da"
+romaji["ヂ"]	= "ji"
+romaji["ヅ"]	= "zu"
+romaji["デ"]	= "de"
+romaji["ド"]	= "do"
+romaji["ヂャ"]	= "ja"
+romaji["ヂュ"]	= "ju"
+romaji["ヂョ"]	= "jo"
+romaji["バ"]	= "ba"
+romaji["ビ"]	= "bi"
+romaji["ブ"]	= "bu"
+romaji["ベ"]	= "be"
+romaji["ボ"]	= "bo"
+romaji["ビャ"]	= "bya"
+romaji["ビュ"]	= "byu"
+romaji["ビョ"]	= "byo"
+romaji["パ"]	= "pa"
+romaji["ピ"]	= "pi"
+romaji["プ"]	= "pu"
+romaji["ペ"]	= "pe"
+romaji["ポ"]	= "po"
+romaji["ピャ"]	= "pya"
+romaji["ピュ"]	= "pyu"
+romaji["ピョ"]	= "pyo"
+romaji["イィ"]	= "yi"
+romaji["イェ"]	= "ye"
+romaji["ウァ"]	= "wa"
+romaji["ウィ"]	= "wi"
+romaji["ウゥ"]	= "wu"
+romaji["ウェ"]	= "we"
+romaji["ウォ"]	= "wo"
+romaji["ウャ"]	= "wya"
+romaji["ウュ"]	= "wyu"
+romaji["ウョ"]	= "wyo"
+romaji["ヴァ"]	= "va"
+romaji["ヴィ"]	= "vi"
+romaji["ヴ"]	= "vu"
+romaji["ヴェ"]	= "ve"
+romaji["ヴォ"]	= "vo"
+romaji["ヴャ"]	= "vya"
+romaji["ヴュ"]	= "vyu"
+romaji["ヴョ"]	= "vyo"
+romaji["クァ"]	= "kwa"
+romaji["クィ"]	= "kwi"
+romaji["クゥ"]	= "kwu"
+romaji["クェ"]	= "kwe"
+romaji["クォ"]	= "kwo"
+romaji["グァ"]	= "gwa"
+romaji["グィ"]	= "gwi"
+romaji["グゥ"]	= "gwu"
+romaji["グェ"]	= "gwe"
+romaji["グォ"]	= "gwo"
+romaji["シェ"]	= "she"
+romaji["ジェ"]	= "je"
+romaji["チェ"]	= "che"
+romaji["ツァ"]	= "tsa"
+romaji["ツィ"]	= "tsi"
+romaji["ツェ"]	= "tse"
+romaji["ツォ"]	= "tso"
+romaji["ティ"]	= "ti"
+romaji["トゥ"]	= "tu"
+romaji["テャ"]	= "tya"
+romaji["テュ"]	= "tyu"
+romaji["テョ"]	= "tyo"
+romaji["ディ"]	= "di"
+romaji["ドゥ"]	= "du"
+romaji["デャ"]	= "dya"
+romaji["デュ"]	= "dyu"
+romaji["デョ"]	= "dyo"
+romaji["ファ"]	= "fa"
+romaji["フィ"]	= "fi"
+romaji["フェ"]	= "fe"
+romaji["フォ"]	= "fo"
+romaji["フャ"]	= "fya"
+romaji["フュ"]	= "fyu"
+romaji["フョ"]	= "fyo"
+romaji["スァ"]	= "swa"
+romaji["スィ"]	= "si"
+romaji["スゥ"]	= "swu"
+romaji["スェ"]	= "swe"
+romaji["スォ"]	= "swo"
+romaji["スャ"]	= "sya"
+romaji["スュ"]	= "syu"
+romaji["スョ"]	= "syo"
+romaji["ズァ"]	= "zwa"
+romaji["ズィ"]	= "zi"
+romaji["ズゥ"]	= "zwu"
+romaji["ズェ"]	= "zwe"
+romaji["ズォ"]	= "zwo"
+romaji["ズャ"]	= "zya"
+romaji["ズュ"]	= "zyu"
+romaji["ズョ"]	= "zyo"
+romaji["テァ"]	= "tha"
+romaji["テゥ"]	= "thu"
+romaji["テェ"]	= "tye"
+romaji["テォ"]	= "tho"
+romaji["デァ"]	= "dha"
+romaji["デゥ"]	= "dhu"
+romaji["デェ"]	= "dye"
+romaji["デォ"]	= "dho"
+romaji["トァ"]	= "twa"
+romaji["トィ"]	= "twi"
+romaji["トェ"]	= "twe"
+romaji["トォ"]	= "two"
+romaji["ドァ"]	= "dwa"
+romaji["ドィ"]	= "dwi"
+romaji["ドェ"]	= "dwe"
+romaji["ドォ"]	= "dwo"
+romaji["ヒィ"]	= "hyi"
+romaji["ヒェ"]	= "hye"
+romaji["ビィ"]	= "byi"
+romaji["ビェ"]	= "bye"
+romaji["ピィ"]	= "pyi"
+romaji["ピェ"]	= "pye"
+romaji["ホァ"]	= "hwa"
+romaji["ホィ"]	= "hwi"
+romaji["ホゥ"]	= "hu"
+romaji["ホェ"]	= "hwe"
+romaji["ホォ"]	= "hwo"
+romaji["ムァ"]	= "mwa"
+romaji["ムィ"]	= "mwi"
+romaji["ムゥ"]	= "mwu"
+romaji["ムェ"]	= "mwe"
+romaji["ムォ"]	= "mwo"
+romaji["ヌァ"]	= "nwa"
+romaji["ヌィ"]	= "nwi"
+romaji["ヌゥ"]	= "nwu"
+romaji["ヌェ"]	= "nwe"
+romaji["ヌォ"]	= "nwo"
+romaji["リィ"]	= "ryi"
+romaji["リェ"]	= "rye"
+
+function romanize(word)
+	local romanized = ""
+	local wordlength = utf8.len(word)
+	local i = 1
+	while i <= wordlength do
+
+		local double = false
+		if utf8.sub(word, i, i) == "っ" then
+			double = true
+			i = i + 1
+		end
+
+		if romaji[utf8.sub(word, i, i + 1)] then
+			chars = 2
+		else
+			chars = 1
+		end
+
+		local letter = romaji[utf8.sub(word, i, i + chars - 1)]
+		if double then
+			letter = string.sub(letter, 1, 1) .. letter
+		end
+		romanized = romanized .. letter
+		i = i + chars
+
+		if utf8.sub(word, i, i) == "ー" then
+			i = i + 1
+			romanized = romanized .. string.sub(romanized, -1)
+		end
+	end
+	return romanized
+end
+
+
+/* license.terms
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties.  The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal 
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license. 
+*/
+/*
+ * tclUniData.c --
+ *
+ *	Declarations of Unicode character information tables.  This file is
+ *	automatically generated by the tools/uniParse.tcl script.  Do not
+ *	modify this file by hand.
+ *
+ * Copyright (c) 1998 by Scriptics Corporation.
+ * All rights reserved.
+ *
+ * RCS: @(#) $Id: slnudata.c,v 1.1.1.1 2006/04/19 15:03:33 erik Exp $
+ */
+
+/*
+ * A 16-bit Unicode character is split into two parts in order to index
+ * into the following tables.  The lower OFFSET_BITS comprise an offset
+ * into a page of characters.  The upper bits comprise the page number.
+ */
+
+extern "C"
+{
+#define OFFSET_BITS 5
+
+/*
+ * The pageMap is indexed by page number and returns an alternate page number
+ * that identifies a unique page of characters.  Many Unicode characters map
+ * to the same alternate page number.
+ */
+
+static unsigned char pageMap[] = {
+    0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, 15, 16, 17, 
+    18, 19, 20, 21, 22, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 7, 32, 
+    7, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 
+    48, 49, 50, 51, 52, 35, 47, 53, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 
+    58, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 80, 81, 
+    84, 85, 80, 86, 87, 88, 89, 90, 91, 92, 35, 93, 94, 95, 35, 96, 97, 
+    98, 99, 100, 101, 102, 35, 47, 103, 104, 35, 35, 105, 106, 107, 47, 
+    47, 108, 47, 47, 109, 47, 110, 111, 47, 112, 47, 113, 114, 115, 116, 
+    114, 47, 117, 118, 35, 47, 47, 119, 90, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 120, 121, 47, 47, 122, 
+    35, 35, 35, 35, 47, 123, 124, 125, 126, 47, 127, 128, 47, 129, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 7, 7, 7, 7, 130, 7, 7, 131, 132, 133, 134, 
+    135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 
+    149, 150, 151, 152, 153, 154, 155, 156, 156, 156, 156, 156, 156, 156, 
+    157, 158, 159, 160, 161, 162, 35, 35, 35, 160, 163, 164, 165, 166, 
+    167, 168, 169, 160, 160, 160, 160, 170, 171, 172, 173, 174, 160, 160, 
+    175, 35, 35, 35, 35, 176, 177, 178, 179, 180, 181, 35, 35, 160, 160, 
+    160, 160, 160, 160, 160, 160, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    182, 160, 160, 155, 160, 160, 160, 160, 160, 160, 170, 183, 184, 185, 
+    90, 47, 186, 90, 47, 187, 188, 189, 47, 47, 190, 128, 35, 35, 191, 
+    192, 193, 194, 192, 195, 196, 197, 160, 160, 160, 198, 160, 160, 199, 
+    197, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 200, 35, 35, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 201, 35, 35, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    202, 203, 204, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 205, 35, 35, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 
+    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 
+    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 
+    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 
+    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 47, 47, 47, 47, 47, 47, 47, 47, 47, 208, 35, 35, 35, 35, 
+    35, 35, 209, 210, 211, 47, 47, 212, 213, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 214, 215, 47, 216, 47, 217, 218, 35, 219, 220, 221, 47, 
+    47, 47, 222, 223, 2, 224, 225, 226, 227, 228, 229, 230, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 231, 35, 232, 233, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
+    47, 208, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 47, 234, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 235, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
+    207, 207, 207, 236, 207, 207, 207, 207, 207, 207, 207, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 
+    35, 35, 35, 35, 35
+};
+
+/*
+ * The groupMap is indexed by combining the alternate page number with
+ * the page offset and returns a group number that identifies a unique
+ * set of character attributes.
+ */
+
+static unsigned char groupMap[] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 
+    3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 3, 10, 10, 10, 
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
+    10, 10, 10, 10, 10, 10, 5, 3, 6, 11, 12, 11, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 5, 7, 6, 7, 1, 2, 3, 4, 4, 4, 4, 14, 14, 11, 14, 15, 16, 
+    7, 8, 14, 11, 14, 7, 17, 17, 11, 18, 14, 3, 11, 17, 15, 19, 17, 17, 
+    17, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
+    10, 10, 10, 10, 10, 10, 10, 10, 7, 10, 10, 10, 10, 10, 10, 10, 15, 
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, 13, 20, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 
+    22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 23, 24, 21, 22, 21, 
+    22, 21, 22, 15, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 
+    22, 21, 22, 15, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 
+    22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 25, 
+    21, 22, 21, 22, 21, 22, 26, 15, 27, 21, 22, 21, 22, 28, 21, 22, 29, 
+    29, 21, 22, 15, 30, 31, 32, 21, 22, 29, 33, 34, 35, 36, 21, 22, 15, 
+    15, 35, 37, 15, 38, 21, 22, 21, 22, 21, 22, 39, 21, 22, 39, 15, 15, 
+    21, 22, 39, 21, 22, 40, 40, 21, 22, 21, 22, 41, 21, 22, 15, 42, 21, 
+    22, 15, 43, 42, 42, 42, 42, 44, 45, 46, 44, 45, 46, 44, 45, 46, 21, 
+    22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 47, 21, 
+    22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 
+    15, 44, 45, 46, 21, 22, 48, 49, 21, 22, 21, 22, 21, 22, 21, 22, 0, 
+    0, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 
+    21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 50, 51, 15, 52, 52, 15, 53, 15, 
+    54, 15, 15, 15, 15, 52, 15, 15, 55, 15, 15, 15, 15, 56, 57, 15, 15, 
+    15, 15, 15, 57, 15, 15, 58, 15, 15, 59, 15, 15, 15, 15, 15, 15, 15, 
+    15, 15, 15, 60, 15, 15, 60, 15, 15, 15, 15, 60, 15, 61, 61, 15, 15, 
+    15, 15, 15, 15, 62, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 63, 
+    63, 63, 63, 63, 63, 63, 63, 63, 11, 11, 63, 63, 63, 63, 63, 63, 63, 
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 63, 63, 11, 
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 63, 63, 63, 63, 
+    63, 11, 11, 11, 11, 11, 11, 11, 11, 11, 63, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 
+    64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 
+    0, 0, 0, 0, 63, 0, 0, 0, 3, 0, 0, 0, 0, 0, 11, 11, 66, 3, 67, 67, 67, 
+    0, 68, 0, 69, 69, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
+    10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 70, 71, 
+    71, 71, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 72, 13, 13, 13, 13, 13, 13, 13, 13, 13, 73, 74, 74, 0, 
+    75, 76, 77, 77, 77, 78, 79, 15, 0, 0, 21, 22, 21, 22, 21, 22, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 80, 81, 47, 
+    15, 82, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 84, 84, 84, 84, 84, 84, 
+    84, 84, 84, 84, 84, 84, 84, 84, 84, 10, 10, 10, 10, 10, 10, 10, 10, 
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
+    10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 13, 13, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 
+    81, 81, 81, 81, 21, 22, 14, 64, 64, 64, 64, 0, 85, 85, 0, 0, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 
+    22, 77, 21, 22, 21, 22, 0, 0, 21, 22, 0, 0, 21, 22, 0, 0, 0, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 
+    22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 
+    21, 22, 0, 0, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 86, 86, 86, 
+    86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 
+    86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 
+    0, 0, 63, 3, 3, 3, 3, 3, 3, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 
+    87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 
+    87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 15, 0, 3, 8, 0, 0, 
+    0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 3, 64, 3, 64, 
+    64, 3, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 0, 0, 0, 0, 0, 42, 42, 42, 3, 3, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 0, 0, 0, 0, 0, 63, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 0, 0, 64, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 3, 42, 64, 
+    64, 64, 64, 64, 64, 64, 85, 85, 64, 64, 64, 64, 64, 64, 63, 63, 64, 
+    64, 14, 64, 64, 64, 64, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 42, 42, 
+    42, 14, 14, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 88, 42, 
+    64, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 
+    64, 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 0, 0, 64, 42, 89, 89, 89, 64, 64, 64, 64, 64, 64, 
+    64, 64, 89, 89, 89, 89, 64, 0, 0, 42, 64, 64, 64, 64, 0, 0, 0, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 64, 64, 3, 3, 9, 9, 9, 9, 9, 9, 
+    9, 9, 9, 9, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 
+    89, 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 0, 0, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 0, 42, 0, 0, 0, 42, 
+    42, 42, 42, 0, 0, 64, 0, 89, 89, 89, 64, 64, 64, 64, 0, 0, 89, 89, 
+    0, 0, 89, 89, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 42, 42, 
+    0, 42, 42, 42, 64, 64, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 42, 42, 
+    4, 4, 17, 17, 17, 17, 17, 17, 14, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 42, 
+    42, 42, 42, 42, 42, 0, 0, 0, 0, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 
+    42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 0, 42, 42, 0, 42, 42, 0, 0, 
+    64, 0, 89, 89, 89, 64, 64, 0, 0, 0, 0, 64, 64, 0, 0, 64, 64, 64, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 0, 42, 0, 0, 0, 0, 0, 
+    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 64, 64, 42, 42, 42, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 89, 0, 42, 42, 42, 42, 42, 42, 42, 
+    0, 42, 0, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 
+    42, 42, 0, 42, 42, 0, 42, 42, 42, 42, 42, 0, 0, 64, 42, 89, 89, 89, 
+    64, 64, 64, 64, 64, 0, 64, 64, 89, 0, 89, 89, 64, 0, 0, 42, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 9, 9, 9, 9, 
+    9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 0, 42, 
+    42, 0, 0, 42, 42, 42, 42, 0, 0, 64, 42, 89, 64, 89, 64, 64, 64, 0, 
+    0, 0, 89, 89, 0, 0, 89, 89, 64, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 0, 
+    0, 0, 0, 42, 42, 0, 42, 42, 42, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 
+    9, 9, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 89, 
+    0, 42, 42, 42, 42, 42, 42, 0, 0, 0, 42, 42, 42, 0, 42, 42, 42, 42, 
+    0, 0, 0, 42, 42, 0, 42, 0, 42, 42, 0, 0, 0, 42, 42, 0, 0, 0, 42, 42, 
+    42, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 0, 0, 0, 
+    0, 89, 89, 64, 89, 89, 0, 0, 0, 89, 89, 89, 0, 89, 89, 89, 64, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 89, 89, 89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 
+    42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 0, 42, 42, 42, 42, 42, 0, 0, 0, 0, 64, 64, 64, 89, 89, 
+    89, 89, 0, 64, 64, 64, 0, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 64, 
+    64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 
+    9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 
+    89, 0, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 0, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 
+    42, 42, 0, 0, 0, 0, 89, 64, 89, 89, 89, 89, 89, 0, 64, 89, 89, 0, 89, 
+    89, 64, 64, 0, 0, 0, 0, 0, 0, 0, 89, 89, 0, 0, 0, 0, 0, 0, 0, 42, 0, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 89, 89, 89, 64, 64, 
+    64, 0, 0, 89, 89, 89, 0, 89, 89, 89, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 89, 0, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 0, 0, 
+    42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 64, 0, 0, 0, 0, 89, 89, 89, 64, 
+    64, 64, 0, 64, 0, 89, 89, 89, 89, 89, 89, 89, 89, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 89, 3, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 64, 42, 42, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 4, 42, 42, 
+    42, 42, 42, 42, 63, 64, 64, 64, 64, 64, 64, 64, 64, 3, 9, 9, 9, 9, 
+    9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0, 0, 42, 42, 0, 42, 0, 0, 42, 42, 
+    0, 42, 0, 0, 42, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 0, 42, 42, 42, 42, 
+    42, 42, 42, 0, 42, 42, 42, 0, 42, 0, 42, 0, 0, 42, 42, 0, 42, 42, 42, 
+    42, 64, 42, 42, 64, 64, 64, 64, 64, 64, 0, 64, 64, 42, 0, 0, 42, 42, 
+    42, 42, 42, 0, 63, 0, 64, 64, 64, 64, 64, 64, 0, 0, 9, 9, 9, 9, 9, 
+    9, 9, 9, 9, 9, 0, 0, 42, 42, 0, 0, 42, 14, 14, 14, 3, 3, 3, 3, 3, 3, 
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 64, 64, 14, 14, 14, 
+    14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 14, 64, 14, 64, 14, 64, 5, 6, 5, 6, 89, 89, 42, 42, 42, 
+    42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 89, 64, 64, 64, 64, 64, 3, 64, 64, 42, 
+    42, 42, 42, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    0, 14, 14, 14, 14, 14, 14, 14, 14, 64, 14, 14, 14, 14, 14, 14, 0, 0, 
+    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 0, 42, 
+    42, 42, 42, 42, 0, 42, 42, 0, 89, 64, 64, 64, 64, 89, 64, 0, 0, 0, 
+    64, 64, 89, 64, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 
+    3, 3, 3, 3, 3, 42, 42, 42, 42, 42, 42, 89, 89, 64, 64, 0, 0, 0, 0, 
+    0, 0, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 
+    77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 
+    77, 77, 77, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    0, 0, 0, 0, 3, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 
+    0, 0, 0, 0, 42, 42, 42, 42, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 42, 42, 42, 
+    42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 
+    0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 0, 42, 
+    0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 
+    42, 0, 42, 0, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 42, 0, 
+    42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 
+    3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 3, 3, 42, 42, 42, 42, 42, 
+    42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 5, 6, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    3, 3, 3, 90, 90, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 89, 89, 89, 64, 64, 64, 64, 64, 64, 64, 89, 89, 89, 89, 89, 
+    89, 89, 89, 64, 89, 89, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    3, 3, 3, 3, 3, 3, 3, 4, 3, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 
+    3, 3, 3, 3, 8, 3, 3, 3, 3, 88, 88, 88, 88, 0, 9, 9, 9, 9, 9, 9, 9, 
+    9, 9, 9, 0, 0, 0, 0, 0, 0, 42, 42, 42, 63, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 
+    0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 64, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 21, 22, 21, 22, 21, 
+    22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 15, 15, 
+    15, 15, 15, 91, 0, 0, 0, 0, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 
+    21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 0, 
+    0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 
+    93, 93, 93, 92, 92, 92, 92, 92, 92, 0, 0, 93, 93, 93, 93, 93, 93, 0, 
+    0, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 
+    92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 92, 
+    92, 92, 92, 92, 92, 0, 0, 93, 93, 93, 93, 93, 93, 0, 0, 15, 92, 15, 
+    92, 15, 92, 15, 92, 0, 93, 0, 93, 0, 93, 0, 93, 92, 92, 92, 92, 92, 
+    92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 95, 95, 95, 95, 
+    96, 96, 97, 97, 98, 98, 99, 99, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 
+    100, 100, 100, 100, 100, 100, 100, 100, 92, 92, 92, 92, 92, 92, 92, 
+    92, 100, 100, 100, 100, 100, 100, 100, 100, 92, 92, 92, 92, 92, 92, 
+    92, 92, 100, 100, 100, 100, 100, 100, 100, 100, 92, 92, 15, 101, 15, 
+    0, 15, 15, 93, 93, 102, 102, 103, 11, 104, 11, 11, 11, 15, 101, 15, 
+    0, 15, 15, 105, 105, 105, 105, 103, 11, 11, 11, 92, 92, 15, 15, 0, 
+    0, 15, 15, 93, 93, 106, 106, 0, 11, 11, 11, 92, 92, 15, 15, 15, 107, 
+    15, 15, 93, 93, 108, 108, 109, 11, 11, 11, 0, 0, 15, 101, 15, 0, 15, 
+    15, 110, 110, 111, 111, 103, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+    2, 2, 2, 88, 88, 88, 88, 8, 8, 8, 8, 8, 8, 3, 3, 16, 19, 5, 16, 16, 
+    19, 5, 16, 3, 3, 3, 3, 3, 3, 3, 3, 112, 113, 88, 88, 88, 88, 88, 2, 
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 16, 19, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 
+    5, 6, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, 88, 88, 88, 17, 
+    0, 0, 0, 17, 17, 17, 17, 17, 17, 7, 7, 7, 5, 6, 15, 17, 17, 17, 17, 
+    17, 17, 17, 17, 17, 17, 7, 7, 7, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 
+    64, 64, 64, 85, 85, 85, 85, 64, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 77, 
+    14, 14, 14, 14, 77, 14, 14, 15, 77, 77, 77, 15, 15, 77, 77, 77, 15, 
+    14, 77, 14, 14, 14, 77, 77, 77, 77, 77, 14, 14, 14, 14, 14, 14, 77, 
+    14, 114, 14, 77, 14, 115, 116, 77, 77, 14, 15, 77, 77, 14, 77, 15, 
+    42, 42, 42, 42, 15, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 
+    117, 117, 117, 117, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118, 
+    118, 118, 118, 118, 118, 118, 118, 90, 90, 90, 90, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14, 
+    14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 7, 
+    14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 119, 119, 119, 119, 119, 119, 
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
+    119, 119, 119, 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 120, 
+    120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 
+    120, 120, 120, 120, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 
+    14, 14, 14, 0, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 0, 14, 0, 14, 14, 14, 14, 0, 0, 0, 14, 0, 14, 14, 
+    14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 17, 17, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 
+    0, 0, 0, 2, 3, 3, 3, 14, 63, 42, 90, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 
+    14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 8, 5, 6, 6, 14, 90, 90, 90, 90, 90, 
+    90, 90, 90, 90, 64, 64, 64, 64, 64, 64, 8, 63, 63, 63, 63, 63, 14, 
+    14, 90, 90, 90, 0, 0, 0, 14, 14, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 64, 64, 
+    11, 11, 63, 63, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 12, 63, 
+    63, 63, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 14, 14, 17, 17, 17, 
+    17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 
+    17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 121, 121, 121, 121, 121, 121, 
+    121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 
+    121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 122, 
+    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 
+    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 
+    122, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 
+    15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 
+    0, 0, 0, 0, 42, 64, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 7, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 42, 42, 42, 42, 
+    42, 0, 42, 0, 42, 42, 0, 42, 42, 0, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 0, 64, 64, 64, 64, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 8, 12, 12, 5, 6, 5, 6, 5, 
+    6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 0, 0, 0, 0, 3, 3, 3, 3, 12, 12, 12, 
+    3, 3, 3, 0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, 3, 3, 7, 8, 7, 7, 7, 
+    0, 3, 4, 3, 3, 0, 0, 0, 0, 42, 42, 42, 0, 42, 0, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    0, 0, 88, 0, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, 9, 9, 9, 
+    9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 11, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 
+    13, 13, 13, 5, 7, 6, 7, 0, 0, 3, 5, 6, 3, 12, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 63, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 63, 
+    63, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 
+    42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 0, 0, 0, 
+    42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 42, 42, 42, 42, 0, 0, 42, 42, 
+    42, 42, 42, 42, 0, 0, 42, 42, 42, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, 
+    14, 7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, 14, 
+    14, 42, 17, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 123, 123, 
+    126, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 89, 64, 14, 14, 14, 
+    14, 14, 0, 0, 77, 77, 15, 15, 77, 15, 15, 77, 77, 15, 77, 77, 15, 77, 
+    77, 15, 15, 77, 15, 15, 77, 77, 15, 77, 77, 15, 77, 77, 15, 15, 77, 
+    15, 15, 77, 77, 15, 77, 77, 15, 77, 77, 15, 15, 77, 77, 15, 15, 77, 
+    15, 15, 77, 77, 15, 15, 77, 15, 15, 77, 77, 15, 15, 9, 9, 9, 42, 42, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 88, 0, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 
+    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 
+    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 
+    122
+};
+
+/*
+ * Each group represents a unique set of character attributes.  The attributes
+ * are encoded into a 32-bit value as follows:
+ *
+ * Bits 0-4	Character category: see the constants listed below.
+ *
+ * Bits 5-7	Case delta type: 000 = identity
+ *				 010 = add delta for lower
+ *				 011 = add delta for lower, add 1 for title
+ *				 100 = sutract delta for title/upper
+ *				 101 = sub delta for upper, sub 1 for title
+ *				 110 = sub delta for upper, add delta for lower
+ *
+ * Bits 8-21	Reserved for future use.
+ *
+ * Bits 22-31	Case delta: delta for case conversions.  This should be the
+ *			    highest field so we can easily sign extend.
+ */
+
+static int groups[] = {
+    0, 15, 12, 25, 27, 21, 22, 26, 20, 9, 134217793, 28, 19, 134217858, 
+    29, 2, 23, 11, 1178599554, 24, -507510654, 4194369, 4194434, -834666431, 
+    973078658, -507510719, 1258291330, 880803905, 864026689, 859832385, 
+    331350081, 847249473, 851443777, 868220993, -406847358, 884998209, 
+    876609601, 893386817, 897581121, 914358337, 910164033, 918552641, 
+    5, -234880894, 8388705, 4194499, 8388770, 331350146, -406847423, 
+    -234880959, 880803970, 864026754, 859832450, 847249538, 851443842, 
+    868221058, 876609666, 884998274, 893386882, 897581186, 914358402, 
+    910164098, 918552706, 4, 6, -352321402, 159383617, 155189313, 
+    268435521, 264241217, 159383682, 155189378, 130023554, 268435586, 
+    264241282, 260046978, 239075458, 1, 197132418, 226492546, 360710274, 
+    335544450, -251658175, 402653314, 335544385, 7, 201326657, 201326722, 
+    16, 8, 10, 247464066, -33554302, -33554367, -310378366, -360710014, 
+    -419430270, -536870782, -469761918, -528482174, -33554365, -37748606, 
+    -310378431, -37748669, 155189378, -360710079, -419430335, -29359998, 
+    -469761983, -29360063, -536870847, -528482239, 13, 14, -1463812031, 
+    -801111999, -293601215, 67108938, 67109002, 109051997, 109052061, 
+    18, 17, 8388673, 12582977, 8388738, 12583042
+};
+
+/*
+ * The following constants are used to determine the category of a
+ * Unicode character.
+ */
+
+#define UNICODE_CATEGORY_MASK 0X1F
+
+enum {
+    UNASSIGNED,
+    UPPERCASE_LETTER,
+    LOWERCASE_LETTER,
+    TITLECASE_LETTER,
+    MODIFIER_LETTER,
+    OTHER_LETTER,
+    NON_SPACING_MARK,
+    ENCLOSING_MARK,
+    COMBINING_SPACING_MARK,
+    DECIMAL_DIGIT_NUMBER,
+    LETTER_NUMBER,
+    OTHER_NUMBER,
+    SPACE_SEPARATOR,
+    LINE_SEPARATOR,
+    PARAGRAPH_SEPARATOR,
+    CONTROL,
+    FORMAT,
+    PRIVATE_USE,
+    SURROGATE,
+    CONNECTOR_PUNCTUATION,
+    DASH_PUNCTUATION,
+    OPEN_PUNCTUATION,
+    CLOSE_PUNCTUATION,
+    INITIAL_QUOTE_PUNCTUATION,
+    FINAL_QUOTE_PUNCTUATION,
+    OTHER_PUNCTUATION,
+    MATH_SYMBOL,
+    CURRENCY_SYMBOL,
+    MODIFIER_SYMBOL,
+    OTHER_SYMBOL
+};
+
+/*
+ * The following macros extract the fields of the character info.  The
+ * GetDelta() macro is complicated because we can't rely on the C compiler
+ * to do sign extension on right shifts.
+ */
+
+#define GetCaseType(info) (((info) & 0xE0) >> 5)
+#define GetCategory(info) ((info) & 0x1F)
+#define GetDelta(info) (((info) > 0) ? ((info) >> 22) : (~(~((info)) >> 22)))
+
+/*
+ * This macro extracts the information about a character from the
+ * Unicode character tables.
+ */
+
+#define GetUniCharInfo(ch) (groups[groupMap[(pageMap[(((int)(ch)) & 0xffff) >> OFFSET_BITS] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))]])
+}
+/*
+*	Selene Unicode/UTF-8
+*	This additions
+*	Copyright (c) 2005 Malete Partner, Berlin, partner@malete.org
+*	Available under "Lua 5.0 license", see http://www.lua.org/license.html#5
+*	$Id: slnunico.c,v 1.5 2006/07/26 17:20:04 paul Exp $
+*
+*	contains code from 
+** lstrlib.c,v 1.109 2004/12/01 15:46:06 roberto Exp
+** Standard library for string operations and pattern-matching
+** See Copyright Notice in lua.h
+*
+*	uses the udata table and a couple of expressions from Tcl 8.4.x UTF-8
+* which comes with the following license.terms:
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties.  The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal 
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license. 
+
+(end of Tcl license terms)
+*/
+
+/*
+According to http://ietf.org/rfc/rfc3629.txt we support up to 4-byte
+(21 bit) sequences encoding the UTF-16 reachable 0-0x10FFFF.
+Any byte not part of a 2-4 byte sequence in that range decodes to itself.
+Ill formed (non-shortest) "C0 80" will be decoded as two code points C0 and 80,
+not code point 0; see security considerations in the RFC.
+However, UTF-16 surrogates (D800-DFFF) are accepted.
+
+See http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
+for default grapheme clusters.
+Lazy westerners we are (and lacking the Hangul_Syllable_Type data),
+we care for base char + Grapheme_Extend, but not for Hangul syllable sequences.
+
+For http://unicode.org/Public/UNIDATA/UCD.html#Grapheme_Extend
+we use Mn (NON_SPACING_MARK) + Me (ENCLOSING_MARK),
+ignoring the 18 mostly south asian Other_Grapheme_Extend (16 Mc, 2 Cf) from
+http://www.unicode.org/Public/UNIDATA/PropList.txt
+*/
+
+extern "C"
+{
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+#ifndef SLN_UNICODENAME /* unless set it luaconf */
+# define SLN_UNICODENAME "unicode"
+#endif
+
+
+#include "slnudata.c"
+#define charinfo(c) (~0xFFFF&(c) ? 0 : GetUniCharInfo(c)) /* BMP only */
+#define charcat(c) (UNICODE_CATEGORY_MASK & charinfo(c))
+#define Grapheme_Extend(code) \
+	(1 & (((1<<NON_SPACING_MARK)|(1<<ENCLOSING_MARK)) >> charcat(code)))
+
+enum { /* operation modes */
+	MODE_ASCII, /* single byte 7bit */
+	MODE_LATIN, /* single byte 8859-1 */
+	MODE_UTF8,	/* UTF-8 by code points */
+	MODE_GRAPH	/* UTF-8 by grapheme clusters */
+#define MODE_MBYTE(mode) (~1&(mode))
+};
+
+
+/* macro to `unsign' a character */
+#define uchar(c)				((unsigned char)(c))
+
+typedef const unsigned char cuc; /* it's just toooo long :) */
+
+
+static void utf8_enco (luaL_Buffer *b, unsigned c)
+{
+	if (0x80 > c) {
+		luaL_addchar(b, c);
+		return;
+	}
+	if (0x800 > c)
+		luaL_addchar(b, 0xC0|(c>>6));
+	else {
+		if (0x10000 > c)
+			luaL_addchar(b, 0xE0|(c>>12));
+		else {
+			luaL_addchar(b, 0xF0|(c>>18));
+			luaL_addchar(b, 0x80|(0x3F&(c>>12)));
+		}
+		luaL_addchar(b, 0x80|(0x3F&(c>>6)));
+	}
+	luaL_addchar(b, 0x80|(0x3F&c));
+}	/* utf8_enco */
+
+
+/* end must be > *pp */
+static unsigned utf8_deco (const char **pp, const char *end)
+{
+	register cuc *p = (cuc*)*pp, * const e = (cuc*)end;
+	unsigned first = *p, code;
+
+	*pp = (const char*)++p; /* eat one */
+	/* check ASCII, dangling cont., non-shortest or not continued */
+	if (0xC2 > first || e == p || 0x80 != (0xC0&*p)) return first;
+	code = 0x3F&*p++; /* save 1st cont. */
+	/* check 2 byte (5+6 = 11 bit) sequence up to 0x7FF */
+	if (0xE0 > first) { /* any >= C2 is valid */
+		code |= (0x1F&first)<<6;
+		goto seq;
+	}
+	if (e != p && 0x80 == (0xC0&*p)) { /* is continued */
+		code = code<<6 | (0x3F&*p++); /* save 2nd */
+		if (0xF0 > first) { /* 3 byte (4+6+6 = 16 bit) seq -- want 2nd cont. */
+			if ( 0xF800&(code |= (0x0F&first)<<12) /* >0x7FF: not non-shortest */
+				/* && 0xD800 != (0xD800 & code) -- nah, let surrogates pass */
+			)
+				goto seq;
+		} else if (e != p && 0x80 == (0xC0&*p) /* check 3rd */
+			/* catch 0xF4 < first and other out-of-bounds */
+			&& 0x110000 > (code = (0x0F&first)<<18 | code<<6 | (0x3F&*p++))
+			&& 0xFFFF < code /* not a 16 bitty */
+		)
+			goto seq;
+	}
+	return first;
+seq:
+	*pp = (const char*)p;
+	return code;
+}	/* utf8_deco */
+
+
+/* reverse decode before pp > start */
+static unsigned utf8_oced (const char **pp, const char *start)
+{
+	register cuc *p = (cuc*)*pp, * const s = (cuc*)start;
+	unsigned last = *--p, code;
+
+	*pp = (const char*)p; /* eat one */
+	/* check non-continuer or at the edge */
+	if (0x80 != (0xC0&last) || s == p) return last;
+	code = 0x3F&last; /* save last cont. */
+	if (0xC0 == (0xE0&*--p)) { /* preceeded by 2 byte seq starter */
+		if (0xC2 <= *p) { code |= (0x1F&*p)<<6; goto seq; }
+	} else if (0x80 == (0xC0&*p) && s<p) {
+		code |= (0x3F&*p)<<6;
+		if (0xE0 == (0xF0&*--p)) { /* 3 byte starter */
+			if (0xF800&(code |= (0x0F&*p)<<12)) goto seq;
+		} else if (0x80 == (0xC0&*p) && s<=--p /* valid 4 byte ? */
+			&& 0x110000 > (code |= (0x0F&*p)<<18 | (0x3F&p[1])<<12)
+			&& 0xFFFF < code
+		)
+			goto seq;
+	}
+	return last;
+seq:
+	*pp = (const char*)p;
+	return code;
+}	/* utf8_oced */
+
+
+/* skip over Grapheme_Extend codes */
+static void utf8_graphext (const char **pp, const char *end)
+{
+	const char *p = *pp;
+	for (; p < end; *pp=p) {
+		unsigned code = utf8_deco(&p, end);
+		if (!Grapheme_Extend(code)) break;
+	}
+}	/* utf8_graphext */
+
+
+static int utf8_count (const char **pp, int bytes, int graph, int max)
+{
+	const char *const end = *pp+bytes;
+	int count = 0;
+	while (*pp < end && count != max) {
+		unsigned code = utf8_deco(pp, end);
+		count++;
+		if (!graph) continue;
+		if (Grapheme_Extend(code) && 1<count) count--; /* uncount */
+	}
+	if (graph && count == max) /* gather more extending */
+		utf8_graphext(pp, end);
+	return count;
+}	/* utf8_count */
+
+
+
+static int unic_len (lua_State *L) {
+	size_t l;
+	const char *s = luaL_checklstring(L, 1, &l);
+	int mode = lua_tointeger(L, lua_upvalueindex(1));
+	if (MODE_MBYTE(mode)) l = (size_t)utf8_count(&s, l, mode-2, -1);
+	lua_pushinteger(L, l);
+	return 1;
+}
+
+
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
+	/* relative string position: negative means back from end */
+	return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
+}
+
+
+static int unic_sub (lua_State *L) {
+	size_t l;
+	const char *s = luaL_checklstring(L, 1, &l), *p, *e=s+l;
+	ptrdiff_t start = luaL_checkinteger(L, 2);
+	ptrdiff_t end = luaL_optinteger(L, 3, -1);
+	int mode = lua_tointeger(L, lua_upvalueindex(1));
+
+	if (MODE_MBYTE(mode)) { p=s; l = (size_t)utf8_count(&p, l, mode-2, -1); }
+	start = posrelat(start, l);
+	end = posrelat(end, l);
+	if (start < 1) start = 1;
+	if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+	if (start > end)
+		lua_pushliteral(L, "");
+	else {
+		l = end - --start; /* #units */
+		if (!(MODE_MBYTE(mode))) /* single byte */
+			s += start;
+		else {
+			if (start) utf8_count(&s, e-s, mode-2, start); /* skip */
+			p = s;
+			utf8_count(&p, e-p, mode-2, l);
+			l = p-s;
+		}
+		lua_pushlstring(L, s, l);
+	}
+	return 1;
+}
+
+
+static int str_reverse (lua_State *L) { /* TODO? whatfor? */
+	size_t l;
+	luaL_Buffer b;
+	const char *s = luaL_checklstring(L, 1, &l), *p = s+l, *q;
+	int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+
+	luaL_buffinit(L, &b);
+	if (!mb)
+		while (s < p--) luaL_addchar(&b, *p);
+	else {
+		unsigned code;
+		while (s < p) {
+			q = p;
+			code = utf8_oced(&p, s);
+			if (MODE_GRAPH == mode)
+				while (Grapheme_Extend(code) && p>s) code = utf8_oced(&p, s);
+			luaL_addlstring(&b, p, q-p);
+		}
+	}
+	luaL_pushresult(&b);
+	return 1;
+}
+
+
+
+static int unic_lower (lua_State *L) {
+	size_t l;
+	luaL_Buffer b;
+	const char *s = luaL_checklstring(L, 1, &l), * const e=s+l;
+	int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+	luaL_buffinit(L, &b);
+	while (s < e) {
+		unsigned c = mb ? utf8_deco(&s, e) : uchar(*s++);
+		int info = charinfo(c);
+		if (GetCaseType(info)&0x02 && (mode || !(0x80&c))) c += GetDelta(info);
+		if (mb) utf8_enco(&b, c); else luaL_addchar(&b, c);
+	}
+	luaL_pushresult(&b);
+	return 1;
+}
+
+
+static int unic_upper (lua_State *L) {
+	size_t l;
+	luaL_Buffer b;
+	const char *s = luaL_checklstring(L, 1, &l), * const e=s+l;
+	int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+	luaL_buffinit(L, &b);
+	while (s < e) {
+		unsigned c = mb ? utf8_deco(&s, e) : uchar(*s++);
+		int info = charinfo(c);
+		if (GetCaseType(info)&0x04 && (mode || !(0x80&c))) c -= GetDelta(info);
+		if (mb) utf8_enco(&b, c); else luaL_addchar(&b, c);
+	}
+	luaL_pushresult(&b);
+	return 1;
+}
+
+
+static int str_rep (lua_State *L) {
+	size_t l;
+	luaL_Buffer b;
+	const char *s = luaL_checklstring(L, 1, &l);
+	int n = luaL_checkint(L, 2);
+	luaL_buffinit(L, &b);
+	while (n-- > 0)
+		luaL_addlstring(&b, s, l);
+	luaL_pushresult(&b);
+	return 1;
+}
+
+
+static int unic_byte (lua_State *L) {
+	size_t l;
+	ptrdiff_t posi, pose;
+	const char *s = luaL_checklstring(L, 1, &l), *p, *e=s+l;
+	int n, mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+
+	if (mb) { p=s; l = (size_t)utf8_count(&p, l, mode-2, -1); }
+	posi = posrelat(luaL_optinteger(L, 2, 1), l);
+	pose = posrelat(luaL_optinteger(L, 3, posi), l);
+	if (posi <= 0) posi = 1;
+	if ((size_t)pose > l) pose = l;
+	if (0 >= (n = pose - --posi)) return 0;	/* empty interval */
+	if (!mb)
+		e = (s += posi) + n;
+	else {
+		if (posi) utf8_count(&s, e-s, mode-2, posi); /* skip */
+		p=s;
+		utf8_count(&p, e-s, mode-2, n);
+		e=p;
+	}
+	/* byte count is upper bound on #elements */
+	luaL_checkstack(L, e-s, "string slice too long");
+	for (n=0; s<e; n++)
+		lua_pushinteger(L, mb ? utf8_deco(&s, e) : uchar(*s++));
+	return n;
+}
+
+
+static int unic_char (lua_State *L) {
+	int i, n = lua_gettop(L);	/* number of arguments */
+	int mode = lua_tointeger(L, lua_upvalueindex(1)), mb = MODE_MBYTE(mode);
+	unsigned lim = mb ? 0x110000 : 0x100;
+ 
+	luaL_Buffer b;
+	luaL_buffinit(L, &b);
+	for (i=1; i<=n; i++) {
+		unsigned c = luaL_checkint(L, i);
+		luaL_argcheck(L, lim > c, i, "invalid value");
+		if (mb) utf8_enco(&b, c); else luaL_addchar(&b, c);
+	}
+	luaL_pushresult(&b);
+	return 1;
+}
+
+
+static int writer (lua_State *L, const void* b, size_t size, void* B) {
+	(void)L;
+	luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+	return 0;
+}
+
+
+static int str_dump (lua_State *L) {
+	luaL_Buffer b;
+	luaL_checktype(L, 1, LUA_TFUNCTION);
+	lua_settop(L, 1);
+	luaL_buffinit(L,&b);
+	if (lua_dump(L, writer, &b) != 0)
+		luaL_error(L, "unable to dump given function");
+	luaL_pushresult(&b);
+	return 1;
+}
+
+
+
+/*
+** {======================================================
+** PATTERN MATCHING
+** =======================================================
+* find/gfind(_aux) -> match, push_captures
+* gsub -> match, add_s (-> push_captures)
+* push_captures, add_s -> push_onecapture
+* match ->
+* 	start/end_capture -> match,
+* 	match_capture, matchbalance, classend -> -,
+* 	min/max_expand -> match, singlematch
+* 	singlematch -> matchbracketclass, match_class,
+* 	matchbracketclass -> match_class -> -,
+*/
+
+
+#define CAP_UNFINISHED	(-1)
+#define CAP_POSITION	(-2)
+
+typedef struct MatchState {
+	const char *src_init;	/* init of source string */
+	const char *src_end;	/* end (`\0') of source string */
+	lua_State *L;
+	int level;	/* total number of captures (finished or unfinished) */
+	int mode;
+	int mb;
+	struct {
+		const char *init;
+		ptrdiff_t len;
+	} capture[LUA_MAXCAPTURES];
+} MatchState;
+
+
+#define L_ESC		'%'
+#define SPECIALS	"^$*+?.([%-"
+
+
+static int check_capture (MatchState *ms, int l) {
+	l -= '1';
+	if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
+		return luaL_error(ms->L, "invalid capture index");
+	return l;
+}
+
+
+static int capture_to_close (MatchState *ms)
+{
+	int level = ms->level;
+	for (level--; level>=0; level--)
+		if (ms->capture[level].len == CAP_UNFINISHED) return level;
+	return luaL_error(ms->L, "invalid pattern capture");
+}
+
+
+static const char *classend (MatchState *ms, const char *p)
+{
+	switch (*p) {
+	case L_ESC:
+		if (!*++p) luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+		break;
+	case '[':
+		/* if (*p == '^') p++; -- no effect */
+		do {	/* look for a `]' */
+			if (!*p) luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+			if (L_ESC == *(p++) && *p) p++;	/* skip escapes (e.g. `%]') */
+		} while (']' != *p);
+		break;
+	default:
+		if (!ms->mb) break;
+		utf8_deco(&p, p+4);
+		return p;
+	}
+	return p+1;
+}	/* classend */
+
+
+/*
+ * The following macros are used for fast character category tests.  The
+ * x_BITS values are shifted right by the category value to determine whether
+ * the given category is included in the set.
+ */ 
+
+#define LETTER_BITS ((1 << UPPERCASE_LETTER) | (1 << LOWERCASE_LETTER) \
+    | (1 << TITLECASE_LETTER) | (1 << MODIFIER_LETTER) | (1 << OTHER_LETTER))
+
+#define DIGIT_BITS (1 << DECIMAL_DIGIT_NUMBER)
+
+#define NUMBER_BITS (1 << DECIMAL_DIGIT_NUMBER) \
+	| (1 << LETTER_NUMBER) | (1 << OTHER_NUMBER)
+
+#define SPACE_BITS ((1 << SPACE_SEPARATOR) | (1 << LINE_SEPARATOR) \
+    | (1 << PARAGRAPH_SEPARATOR))
+
+#define CONNECTOR_BITS (1 << CONNECTOR_PUNCTUATION)
+
+#define PUNCT_BITS ((1 << CONNECTOR_PUNCTUATION) | \
+	    (1 << DASH_PUNCTUATION) | (1 << OPEN_PUNCTUATION) | \
+	    (1 << CLOSE_PUNCTUATION) | (1 << INITIAL_QUOTE_PUNCTUATION) | \
+	    (1 << FINAL_QUOTE_PUNCTUATION) | (1 << OTHER_PUNCTUATION))
+
+
+/* character c matches class cl. undefined for cl not ascii */
+static int match_class (int c, int cl, int mode)
+{
+	int msk, res;
+
+	switch (0x20|cl /*tolower*/) {
+	case 'a' : msk = LETTER_BITS; break;
+	case 'c' : msk = 1<<CONTROL; break;
+	case 'x' : /* hexdigits */
+		if (0x40==(~0x3f&c)/*64-127*/ && 1&(0x7e/*a-f*/>>(0x1f&c))) goto matched;
+	case 'd' : msk = 1<<DECIMAL_DIGIT_NUMBER; mode=0;/* ASCII only */ break;
+	case 'l' : msk = 1<<LOWERCASE_LETTER; break;
+	case 'n' : msk = NUMBER_BITS; break; /* new */
+	case 'p' : msk = PUNCT_BITS; break;
+	case 's' :
+#define STDSPACE /* standard "space" controls 9-13 */ \
+		(1<<9/*TAB*/|1<<10/*LF*/|1<<11/*VT*/|1<<12/*FF*/|1<<13/*CR*/)
+		if (!(~0x1f & c) && 1&(STDSPACE >> c)) goto matched;
+		msk = SPACE_BITS;
+		break;
+	case 'u' : msk = 1<<UPPERCASE_LETTER; break;
+	/*
+		this is not compatible to lua 5.1, where %w is just a letter or a digit
+	case 'w' : msk = LETTER_BITS|NUMBER_BITS|CONNECTOR_BITS; break;
+	*/
+	case 'w' : msk = LETTER_BITS|NUMBER_BITS; break;
+	case 'z' : if (!c) goto matched; msk = 0; break;
+	default: return cl == c;
+	}
+	res = 1 & (msk >> charcat(c));
+	if (!mode && 0x80&c) res = 0;
+	if (0) {
+matched:
+		res = 1;
+	}
+	return 0x20&cl /*islower*/ ? res : !res;
+}	/* match_class */
+
+
+/* decode single byte or UTF-8 seq; advance *s */
+static unsigned deco (const MatchState *ms, const char **s, const char *e)
+{
+	return ms->mb ? utf8_deco(s, e) : *(unsigned char*)(*s)++;
+}
+
+/* s must be < ms->src_end, p < ep */
+static const char *singlematch (const MatchState *ms,
+	const char *s, const char *p, const char *ep)
+{
+	int neg = 0;
+	unsigned c1, c2;
+	unsigned c;
+#ifdef OPTIMIZE_SIZE
+	c = deco(ms, &s, ms->src_end);
+#else
+	if (!ms->mb || !(0x80&*s))
+		c = *(unsigned char*)s++;
+	else
+		c = utf8_deco(&s, ms->src_end);
+#endif
+
+	switch (*p) {
+	case L_ESC:
+		if (match_class(c, uchar(p[1]), ms->mode)) {
+	case '.': /* the all class */
+#ifndef OPTIMIZE_SIZE
+			if (MODE_GRAPH != ms->mode) return s; /* common fast path */
+#endif
+			goto matched_class;
+		}
+		s = 0;
+		break;
+	default:
+#ifdef OPTIMIZE_SIZE
+		c1 = deco(ms, &p, ep);
+#else
+		if (!ms->mb || !(0x80&*p))
+			c1 = *(unsigned char*)p++;
+		else
+			c1 = utf8_deco(&p, ep);
+#endif
+		if (c != c1) s = 0;
+		break;
+	case '[': /* matchbracketclass */
+		ep--; /* now on the ']' */
+		if ((neg = '^' == *++p)) p++;	/* skip the `^' */
+		while (p < ep) {
+			if (*p == L_ESC) {
+				if (match_class(c, uchar(*++p), ms->mode)) goto matched_class_in_brack;
+				p++;
+				continue;
+			}
+			c1 = deco(ms, &p, ep);
+			/* in lua-5.1 and 5.1.1 a trailing '-' is allowed
+				dynasm.lua relies on this
+			*/
+			if ( ep <= p + 1 || '-' != *p ) {
+				const char *op = p, *es;
+				if (MODE_GRAPH == ms->mode) utf8_graphext(&p, ep);
+				if (c != c1) continue;
+				if (MODE_GRAPH != ms->mode) goto matched;
+				/* comp grapheme extension */
+				es = s;
+				utf8_graphext(&es, ms->src_end);
+				if (es-s == p-op && (es==s || !memcmp(s, op, es-s))) goto matched;
+				continue;
+
+			}
+			++p;
+			/* range c1-c2 -- no extend support in range bounds... */
+			/* if (ep == ++p) break; see above */ /* bugger - trailing dash */
+			c2 = deco(ms, &p, ep);
+			if (c2 < c1) { unsigned swap=c1; c1=c2; c2=swap; }
+			if (c1 <= c && c <= c2) goto matched_class_in_brack; /* ...but extend match */
+		}
+		/* not matched */
+		neg = !neg;
+	matched:
+		if (neg) s = 0;
+		/* matchbracketclass */
+	}
+	return s;
+matched_class_in_brack: /* matched %something or range in [] */
+	if (neg)
+		s = 0;
+	else {
+matched_class: /* matched %something or . */
+		if (MODE_GRAPH == ms->mode) utf8_graphext(&s, ms->src_end);
+	}
+	return s;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p);
+
+
+static const char *matchbalance (MatchState *ms, const char *s,
+																	 const char *p) {
+	if (*p == 0 || *(p+1) == 0)
+		luaL_error(ms->L, "unbalanced pattern");
+	if (*s != *p) return NULL;
+	else {
+		int b = *p;
+		int e = *(p+1);
+		int cont = 1;
+		while (++s < ms->src_end) {
+			if (*s == e) {
+				if (--cont == 0) return s+1;
+			}
+			else if (*s == b) cont++;
+		}
+	}
+	return NULL;	/* string ends out of balance */
+}
+
+
+static const char *max_expand (MatchState *ms,
+	const char *s, const char *p, const char *ep)
+{
+	const char *sp = s, *es;
+	while (sp<ms->src_end && (es = singlematch(ms, sp, p, ep)))
+		sp = es;
+	/* keeps trying to match with the maximum repetitions */
+	while (sp>=s) {
+		const char *res = match(ms, sp, ep+1);
+		if (res || sp==s) return res;
+		if (!ms->mb)
+			sp--;	/* else didn't match; reduce 1 repetition to try again */
+		else {
+			unsigned code = utf8_oced(&sp, s);
+			if (MODE_GRAPH == ms->mode)
+				while (Grapheme_Extend(code) && sp>s) code = utf8_oced(&sp, s);
+		}
+	}
+	return NULL;
+}
+
+
+static const char *min_expand (MatchState *ms,
+	const char *s, const char *p, const char *ep)
+{
+	do {
+		const char *res = match(ms, s, ep+1);
+		if (res) return res;
+		if (s >= ms->src_end) break;
+	} while ((s = singlematch(ms, s, p, ep))); /* try with one more repetition */
+	return NULL;
+}
+
+
+static const char *start_capture (MatchState *ms, const char *s,
+																		const char *p, int what) {
+	const char *res;
+	int level = ms->level;
+	if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
+	ms->capture[level].init = s;
+	ms->capture[level].len = what;
+	ms->level = level+1;
+	if ((res=match(ms, s, p)) == NULL)	/* match failed? */
+		ms->level--;	/* undo capture */
+	return res;
+}
+
+
+static const char *end_capture (MatchState *ms, const char *s,
+																	const char *p) {
+	int l = capture_to_close(ms);
+	const char *res;
+	ms->capture[l].len = s - ms->capture[l].init;	/* close capture */
+	if ((res = match(ms, s, p)) == NULL)	/* match failed? */
+		ms->capture[l].len = CAP_UNFINISHED;	/* undo capture */
+	return res;
+}
+
+
+static const char *match_capture (MatchState *ms, const char *s, int l) {
+	size_t len;
+	l = check_capture(ms, l);
+	len = ms->capture[l].len;
+	if ((size_t)(ms->src_end-s) >= len &&
+			memcmp(ms->capture[l].init, s, len) == 0)
+		return s+len;
+	else return NULL;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p) {
+	init: /* using goto's to optimize tail recursion */
+	switch (*p) {
+		case '(': {	/* start capture */
+			if (*(p+1) == ')')	/* position capture? */
+				return start_capture(ms, s, p+2, CAP_POSITION);
+			else
+				return start_capture(ms, s, p+1, CAP_UNFINISHED);
+		}
+		case ')': {	/* end capture */
+			return end_capture(ms, s, p+1);
+		}
+		case L_ESC: {
+			switch (*(p+1)) {
+				case 'b': {	/* balanced string? */
+					s = matchbalance(ms, s, p+2);
+					if (s == NULL) return NULL;
+					p+=4; goto init;	/* else return match(ms, s, p+4); */
+				}
+#if 0 /* TODO */
+				case 'f': {	/* frontier? */
+					const char *ep; char previous;
+					p += 2;
+					if (*p != '[')
+						luaL_error(ms->L, "missing " LUA_QL("[") " after "
+								LUA_QL("%%f") " in pattern" );
+						luaL_error(ms->L, "missing `[' after `%%f' in pattern");
+					ep = classend(ms, p);	/* points to what is next */
+					/* with UTF-8, getting the previous is more complicated */
+					previous = (s == ms->src_init) ? '\0' : *(s-1);
+					/* use singlematch to apply all necessary magic */
+					if (singlematch(uchar(previous), p, ep-1) ||
+						 !singlematch(uchar(*s), p, ep-1)) return NULL;
+					p=ep; goto init;	/* else return match(ms, s, ep); */
+				}
+#endif
+				default: {
+					if (isdigit(uchar(*(p+1)))) {	/* capture results (%0-%9)? */
+						s = match_capture(ms, s, uchar(*(p+1)));
+						if (s == NULL) return NULL;
+						p+=2; goto init;	/* else return match(ms, s, p+2) */
+					}
+					goto dflt;	/* case default */
+				}
+			}
+		}
+		case '\0': {	/* end of pattern */
+			return s;	/* match succeeded */
+		}
+		case '$': {
+			if (*(p+1) == '\0')	/* is the `$' the last char in pattern? */
+				return (s == ms->src_end) ? s : NULL;	/* check end of string */
+			else goto dflt; /* ??? */
+		}
+		default: dflt: {	/* it is a pattern item */
+			const char *ep = classend(ms, p);	/* points to what is next */
+			const char *es = 0;
+			if (s < ms->src_end) es = singlematch(ms, s, p, ep);
+			switch (*ep) {
+				case '?': {	/* optional */
+					const char *res;
+					if (es && (res=match(ms, es, ep+1))) return res;
+					p=ep+1; goto init;	/* else return match(ms, s, ep+1); */
+				}
+				case '*': {	/* 0 or more repetitions */
+					return max_expand(ms, s, p, ep);
+				}
+				case '+': {	/* 1 or more repetitions */
+					return (es ? max_expand(ms, es, p, ep) : NULL);
+				}
+				case '-': {	/* 0 or more repetitions (minimum) */
+					return min_expand(ms, s, p, ep);
+				}
+				default: {
+					if (!es) return NULL;
+					s=es; p=ep; goto init;	/* else return match(ms, s+1, ep); */
+				}
+			}
+		}
+	}
+}
+
+
+
+static const char *lmemfind (const char *s1, size_t l1,
+															 const char *s2, size_t l2) {
+	if (l2 == 0) return s1;	/* empty strings are everywhere */
+	else if (l2 > l1) return NULL;	/* avoids a negative `l1' */
+	else {
+		const char *init;	/* to search for a `*s2' inside `s1' */
+		l2--;	/* 1st char will be checked by `memchr' */
+		l1 = l1-l2;	/* `s2' cannot be found after that */
+		while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
+			init++;	 /* 1st char is already checked */
+			if (memcmp(init, s2+1, l2) == 0)
+				return init-1;
+			else {	/* correct `l1' and `s1' to try again */
+				l1 -= init-s1;
+				s1 = init;
+			}
+		}
+		return NULL;	/* not found */
+	}
+}
+
+
+static void push_onecapture (MatchState *ms, int i, const char *s,
+		const char *e )
+{
+	if (i >= ms->level) {
+		if (i == 0)  /* ms->level == 0, too */
+			lua_pushlstring(ms->L, s, e - s);  /* add whole match */
+		else
+			luaL_error(ms->L, "invalid capture index");
+	}
+	else {
+		ptrdiff_t l = ms->capture[i].len;
+		if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+		if (l == CAP_POSITION)
+			lua_pushinteger(ms->L, ms->capture[i].init - ms->src_in