diff --git a/.classpath b/.classpath deleted file mode 100644 index fb565a5..0000000 --- a/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.gitignore b/.gitignore index f837fa2..9b2785d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ -bin/ -*.class -*MyTest.java -data/ -model/ +*.iml +/.idea +/.classpath +/.project +/target/ +src/test/dataset/test.predict +src/test/model.cnn diff --git a/.project b/.project deleted file mode 100644 index 8f8ffe9..0000000 --- a/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - JavaCNN - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 7341ab1..0000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,11 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 diff --git a/dataset/readme.md b/dataset/readme.md deleted file mode 100644 index 3cda064..0000000 --- a/dataset/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -

The dataset is part of MNIST from kaggle Digit Recognizer competition.

-

"train.format" is the train set, which has been binarized.

-

"test.format" is the test set, which has been binarized.

\ No newline at end of file diff --git a/dataset/test.predict b/dataset/test.predict deleted file mode 100644 index c6eb184..0000000 --- a/dataset/test.predict +++ /dev/null @@ -1,28000 +0,0 @@ -2 -0 -9 -9 -3 -7 -0 -3 -0 -3 -5 -7 -4 -0 -4 -0 -3 -1 -9 -0 -9 -1 -1 -5 -7 -4 -2 -7 -7 -7 -7 -5 -4 -2 -6 -2 -5 -5 -1 -6 -7 -7 -4 -9 -6 -7 -8 -2 -6 -7 -6 -8 -8 -3 -8 -2 -1 -2 -9 -0 -4 -1 -7 -0 -0 -0 -1 -9 -0 -1 -6 -5 -8 -8 -2 -8 -9 -9 -2 -3 -5 -9 -1 -0 -9 -2 -4 -3 -6 -7 -2 -0 -6 -6 -1 -4 -3 -9 -7 -4 -0 -3 -2 -0 -7 -3 -0 -5 -0 -9 -0 -0 -6 -1 -1 -7 -1 -1 -5 -3 -3 -7 -2 -8 -6 -3 -8 -7 -8 -4 -5 -5 -6 -0 -0 -0 -3 -1 -3 -0 -4 -3 -4 -5 -5 -8 -7 -7 -2 -8 -4 -3 -5 -6 -5 -1 -7 -5 -7 -8 -3 -0 -4 -5 -1 -2 -7 -6 -5 -0 -2 -7 -9 -6 -1 -3 -7 -4 -1 -2 -4 -2 -5 -2 -4 -9 -2 -1 -6 -0 -6 -1 -4 -2 -6 -0 -9 -7 -6 -9 -1 -9 -0 -5 -9 -0 -8 -4 -6 -2 -0 -9 -3 -6 -7 -2 -1 -6 -3 -4 -2 -3 -1 -3 -2 -8 -4 -6 -1 -0 -0 -4 -9 -1 -7 -3 -2 -2 -8 -6 -8 -6 -2 -8 -5 -5 -9 -8 -3 -8 -9 -7 -1 -3 -8 -4 -5 -1 -4 -3 -6 -3 -3 -5 -7 -0 -6 -8 -5 -1 -6 -0 -6 -3 -9 -9 -1 -5 -8 -4 -0 -9 -2 -0 -5 -3 -7 -8 -9 -9 -5 -9 -7 -9 -9 -6 -3 -0 -3 -3 -6 -9 -8 -2 -6 -2 -7 -1 -4 -5 -8 -5 -9 -0 -0 -3 -8 -4 -1 -5 -9 -1 -1 -9 -8 -4 -5 -1 -5 -7 -6 -3 -1 -3 -0 -9 -0 -6 -6 -0 -6 -7 -1 -8 -6 -0 -6 -5 -2 -2 -6 -7 -7 -2 -5 -8 -9 -9 -2 -1 -9 -6 -3 -8 -9 -2 -3 -8 -1 -6 -4 -8 -9 -9 -7 -6 -9 -5 -3 -7 -6 -5 -5 -9 -2 -6 -2 -1 -3 -7 -1 -7 -9 -9 -6 -1 -1 -1 -7 -3 -9 -7 -6 -1 -1 -1 -2 -3 -5 -5 -5 -0 -4 -1 -2 -3 -1 -1 -3 -5 -9 -6 -6 -5 -3 -1 -4 -7 -4 -7 -4 -8 -5 -2 -6 -1 -3 -9 -5 -0 -8 -4 -7 -4 -9 -4 -1 -5 -3 -9 -9 -7 -6 -9 -5 -9 -2 -3 -1 -6 -6 -7 -5 -0 -5 -1 -7 -4 -4 -1 -1 -4 -9 -5 -6 -0 -1 -3 -1 -0 -4 -8 -1 -2 -7 -9 -4 -8 -3 -7 -0 -4 -2 -4 -2 -7 -6 -3 -2 -0 -6 -5 -9 -2 -1 -8 -3 -3 -0 -6 -7 -5 -8 -7 -5 -3 -1 -7 -6 -3 -7 -9 -0 -7 -7 -1 -0 -1 -1 -7 -0 -5 -3 -8 -5 -5 -6 -5 -7 -3 -0 -2 -8 -2 -0 -3 -0 -9 -2 -1 -1 -3 -0 -5 -0 -0 -7 -5 -6 -2 -0 -3 -1 -1 -6 -5 -4 -1 -1 -4 -7 -5 -3 -6 -0 -4 -8 -2 -4 -2 -5 -1 -2 -6 -9 -1 -7 -5 -8 -0 -8 -8 -4 -5 -3 -6 -6 -6 -0 -3 -1 -1 -7 -1 -6 -2 -8 -5 -6 -4 -7 -4 -3 -3 -2 -4 -7 -0 -0 -9 -8 -5 -9 -4 -0 -8 -7 -3 -6 -7 -6 -1 -8 -6 -1 -9 -7 -7 -8 -3 -0 -9 -9 -6 -7 -7 -4 -4 -1 -8 -4 -9 -0 -0 -8 -2 -4 -3 -3 -7 -2 -3 -4 -0 -4 -2 -1 -3 -3 -6 -3 -9 -4 -3 -8 -7 -7 -6 -6 -0 -6 -9 -8 -1 -1 -3 -4 -6 -9 -9 -2 -6 -0 -1 -8 -4 -3 -9 -8 -8 -4 -0 -5 -0 -6 -0 -9 -4 -6 -0 -5 -8 -1 -5 -7 -6 -2 -3 -7 -8 -9 -3 -1 -0 -1 -0 -6 -9 -7 -0 -7 -1 -3 -2 -2 -7 -1 -6 -1 -5 -4 -4 -3 -4 -3 -9 -8 -7 -8 -6 -4 -9 -4 -4 -1 -4 -7 -1 -1 -2 -2 -0 -4 -0 -4 -0 -0 -8 -1 -8 -6 -5 -0 -1 -5 -3 -4 -6 -3 -1 -1 -6 -9 -8 -3 -5 -5 -4 -5 -8 -5 -0 -4 -0 -4 -3 -1 -6 -9 -7 -1 -1 -3 -3 -1 -9 -9 -6 -9 -1 -5 -9 -7 -3 -4 -4 -0 -9 -7 -4 -3 -0 -5 -0 -1 -9 -0 -4 -4 -2 -8 -4 -5 -9 -3 -9 -6 -1 -5 -5 -1 -9 -0 -8 -4 -6 -7 -2 -1 -5 -8 -9 -7 -7 -2 -8 -1 -3 -6 -5 -0 -9 -1 -4 -2 -3 -6 -9 -2 -3 -4 -5 -4 -2 -3 -3 -1 -1 -0 -1 -4 -9 -1 -1 -2 -7 -1 -5 -4 -9 -1 -7 -6 -0 -4 -2 -9 -9 -1 -1 -5 -3 -5 -7 -9 -7 -7 -3 -2 -7 -2 -0 -4 -7 -1 -6 -4 -6 -1 -5 -7 -3 -5 -9 -4 -7 -9 -6 -6 -3 -3 -2 -1 -4 -1 -3 -7 -7 -9 -5 -6 -0 -6 -1 -0 -9 -3 -2 -9 -2 -6 -7 -5 -2 -3 -2 -8 -3 -0 -2 -7 -9 -4 -0 -0 -5 -1 -8 -8 -5 -3 -2 -9 -6 -7 -0 -8 -0 -7 -4 -3 -8 -7 -9 -7 -7 -0 -5 -3 -2 -1 -9 -0 -6 -8 -3 -6 -2 -2 -9 -0 -9 -0 -7 -1 -3 -4 -6 -3 -9 -2 -6 -3 -7 -3 -7 -2 -3 -4 -9 -5 -9 -9 -6 -2 -6 -1 -5 -5 -1 -9 -1 -8 -9 -4 -8 -3 -5 -2 -0 -1 -6 -1 -9 -6 -2 -7 -7 -6 -6 -2 -6 -3 -5 -9 -1 -1 -3 -6 -5 -0 -0 -6 -0 -9 -4 -7 -0 -5 -9 -8 -3 -7 -6 -7 -2 -6 -1 -2 -9 -3 -0 -2 -3 -7 -7 -6 -6 -3 -1 -3 -1 -0 -1 -7 -6 -8 -3 -9 -3 -4 -2 -9 -1 -8 -2 -0 -6 -4 -6 -7 -2 -4 -1 -0 -5 -2 -6 -9 -9 -8 -5 -4 -1 -6 -3 -5 -6 -1 -2 -0 -0 -8 -0 -3 -6 -8 -7 -7 -7 -0 -0 -2 -1 -2 -8 -4 -5 -5 -3 -6 -7 -8 -4 -7 -4 -9 -1 -8 -0 -9 -1 -7 -0 -6 -4 -5 -2 -4 -5 -8 -2 -9 -1 -8 -6 -2 -7 -2 -5 -3 -8 -9 -9 -0 -7 -0 -3 -0 -9 -7 -3 -3 -8 -8 -9 -3 -2 -5 -4 -6 -8 -3 -8 -1 -7 -9 -6 -4 -0 -6 -2 -8 -4 -5 -9 -6 -7 -8 -2 -0 -0 -5 -0 -5 -9 -4 -9 -9 -5 -4 -3 -0 -5 -4 -1 -9 -1 -7 -9 -9 -5 -7 -8 -6 -4 -1 -9 -3 -1 -6 -6 -0 -1 -5 -5 -7 -6 -1 -3 -1 -9 -4 -2 -2 -6 -9 -9 -8 -1 -1 -0 -1 -6 -0 -4 -0 -2 -7 -6 -1 -4 -7 -0 -7 -1 -0 -7 -1 -1 -9 -8 -0 -6 -5 -9 -8 -6 -3 -6 -6 -6 -1 -1 -4 -0 -7 -8 -0 -4 -6 -7 -5 -5 -9 -6 -2 -4 -7 -5 -9 -3 -5 -1 -8 -0 -9 -6 -8 -1 -3 -0 -3 -1 -9 -1 -4 -5 -8 -2 -2 -9 -1 -3 -3 -0 -5 -6 -1 -8 -3 -6 -7 -2 -3 -2 -9 -7 -1 -5 -9 -8 -7 -3 -8 -4 -5 -8 -2 -1 -6 -7 -6 -1 -1 -0 -5 -0 -9 -1 -7 -4 -0 -9 -7 -5 -9 -8 -8 -7 -4 -4 -3 -7 -9 -4 -7 -2 -7 -4 -1 -5 -7 -2 -9 -5 -9 -8 -4 -5 -9 -1 -5 -1 -9 -3 -7 -6 -1 -7 -9 -2 -5 -6 -1 -8 -5 -0 -8 -8 -4 -7 -1 -9 -6 -8 -9 -4 -9 -9 -6 -5 -2 -7 -9 -8 -0 -4 -9 -0 -8 -8 -9 -0 -9 -0 -9 -7 -0 -8 -5 -5 -3 -6 -2 -5 -3 -1 -7 -3 -1 -0 -6 -5 -9 -3 -3 -9 -4 -8 -8 -7 -6 -4 -4 -0 -7 -9 -9 -6 -7 -3 -8 -9 -5 -0 -8 -6 -0 -3 -0 -1 -8 -3 -8 -6 -0 -1 -3 -0 -7 -3 -6 -9 -2 -3 -1 -7 -7 -9 -5 -9 -9 -3 -1 -5 -8 -3 -2 -5 -4 -1 -8 -4 -0 -2 -0 -1 -0 -0 -7 -1 -5 -5 -5 -9 -9 -7 -9 -4 -6 -8 -1 -9 -2 -7 -4 -8 -5 -0 -5 -9 -8 -7 -5 -0 -1 -7 -9 -6 -3 -0 -8 -7 -5 -2 -6 -1 -7 -2 -3 -8 -8 -1 -4 -6 -2 -4 -0 -2 -3 -6 -3 -8 -2 -9 -1 -8 -2 -5 -8 -7 -7 -6 -2 -0 -3 -2 -5 -1 -5 -9 -3 -3 -1 -9 -3 -2 -1 -1 -2 -6 -1 -9 -4 -4 -9 -6 -6 -7 -5 -9 -6 -6 -1 -0 -7 -8 -8 -5 -3 -7 -7 -7 -1 -4 -6 -1 -0 -0 -1 -7 -7 -2 -8 -9 -8 -2 -4 -8 -1 -3 -5 -1 -3 -3 -6 -6 -5 -8 -8 -3 -4 -5 -9 -8 -2 -0 -1 -3 -3 -5 -6 -5 -3 -6 -1 -3 -3 -7 -1 -5 -6 -6 -1 -7 -4 -1 -9 -0 -2 -8 -0 -7 -1 -3 -0 -7 -0 -7 -7 -1 -5 -8 -4 -9 -7 -0 -7 -1 -5 -3 -6 -2 -4 -7 -1 -6 -5 -9 -3 -4 -1 -9 -4 -0 -3 -5 -1 -0 -0 -5 -3 -9 -4 -9 -1 -0 -0 -5 -7 -1 -6 -8 -3 -7 -0 -3 -8 -2 -8 -6 -7 -9 -1 -8 -4 -5 -3 -1 -5 -2 -2 -5 -3 -8 -8 -2 -7 -4 -1 -5 -7 -0 -6 -6 -2 -3 -2 -2 -9 -1 -9 -6 -9 -2 -2 -6 -0 -9 -0 -0 -0 -0 -3 -0 -4 -3 -6 -7 -8 -6 -0 -5 -1 -8 -5 -6 -0 -2 -7 -1 -1 -3 -9 -9 -3 -0 -8 -5 -9 -6 -8 -3 -1 -0 -0 -9 -0 -6 -6 -2 -4 -3 -0 -2 -7 -1 -5 -8 -5 -8 -8 -4 -7 -4 -3 -6 -5 -7 -3 -1 -6 -7 -1 -3 -1 -5 -3 -1 -5 -2 -2 -6 -9 -0 -2 -1 -2 -7 -4 -4 -9 -3 -0 -9 -5 -1 -9 -6 -9 -7 -6 -5 -0 -1 -1 -3 -8 -4 -0 -0 -0 -3 -7 -9 -8 -8 -9 -9 -1 -5 -0 -9 -1 -7 -2 -0 -5 -9 -0 -6 -9 -2 -4 -2 -1 -4 -4 -4 -8 -8 -6 -5 -6 -1 -1 -5 -9 -3 -9 -7 -0 -7 -6 -5 -8 -6 -6 -0 -7 -4 -5 -1 -7 -7 -3 -5 -6 -8 -5 -3 -6 -9 -5 -6 -1 -9 -5 -0 -9 -4 -9 -1 -8 -4 -0 -9 -3 -0 -9 -4 -6 -4 -0 -1 -0 -1 -7 -5 -9 -8 -7 -8 -6 -2 -0 -0 -5 -7 -9 -6 -1 -6 -7 -2 -5 -9 -7 -1 -1 -4 -1 -6 -6 -7 -0 -2 -8 -7 -0 -9 -4 -6 -2 -6 -7 -3 -2 -9 -6 -5 -2 -5 -8 -5 -6 -9 -2 -7 -7 -9 -3 -4 -9 -2 -8 -0 -2 -4 -0 -9 -4 -5 -8 -8 -9 -3 -3 -5 -9 -0 -7 -0 -5 -5 -1 -9 -1 -9 -9 -4 -6 -4 -6 -8 -9 -0 -0 -8 -2 -1 -6 -8 -2 -0 -0 -2 -1 -5 -7 -3 -3 -5 -9 -6 -2 -3 -4 -3 -7 -4 -3 -2 -6 -6 -1 -5 -8 -0 -6 -7 -6 -2 -2 -4 -0 -6 -2 -1 -5 -2 -5 -7 -5 -6 -2 -0 -6 -8 -2 -4 -4 -5 -1 -6 -8 -1 -4 -6 -6 -1 -5 -2 -0 -0 -0 -1 -1 -4 -7 -0 -3 -6 -5 -0 -5 -3 -0 -8 -9 -1 -5 -7 -3 -3 -6 -1 -6 -1 -9 -5 -2 -0 -7 -9 -0 -2 -7 -4 -4 -6 -0 -9 -6 -8 -9 -1 -7 -4 -7 -9 -9 -7 -4 -8 -5 -9 -5 -5 -1 -9 -3 -6 -4 -0 -2 -6 -1 -8 -0 -4 -2 -1 -2 -6 -7 -3 -7 -9 -1 -5 -6 -4 -0 -1 -4 -2 -1 -1 -4 -2 -2 -1 -1 -7 -9 -4 -8 -0 -8 -9 -5 -8 -9 -4 -6 -3 -3 -3 -9 -0 -3 -6 -9 -1 -2 -6 -0 -6 -0 -5 -0 -0 -1 -8 -0 -8 -2 -0 -1 -5 -3 -9 -5 -7 -6 -8 -8 -7 -9 -0 -3 -2 -6 -0 -5 -6 -9 -6 -5 -4 -2 -1 -9 -3 -6 -6 -8 -7 -2 -2 -0 -3 -4 -5 -3 -3 -1 -5 -4 -5 -9 -7 -0 -1 -6 -5 -3 -2 -6 -4 -2 -5 -9 -3 -4 -6 -3 -5 -8 -2 -8 -9 -8 -7 -3 -3 -9 -9 -4 -6 -7 -3 -6 -9 -9 -6 -6 -0 -9 -9 -9 -9 -4 -1 -7 -2 -8 -5 -0 -5 -6 -7 -1 -8 -0 -8 -0 -3 -0 -2 -4 -9 -1 -1 -6 -7 -6 -7 -5 -3 -6 -6 -3 -9 -8 -7 -8 -8 -9 -0 -0 -7 -7 -1 -6 -0 -3 -1 -9 -8 -5 -1 -7 -0 -1 -0 -5 -9 -9 -0 -1 -9 -0 -9 -9 -4 -2 -2 -5 -5 -0 -0 -5 -9 -9 -3 -4 -2 -5 -0 -0 -3 -2 -3 -5 -9 -0 -1 -9 -5 -9 -8 -2 -0 -3 -4 -4 -1 -0 -8 -3 -5 -5 -6 -9 -1 -9 -8 -7 -0 -3 -3 -9 -1 -0 -3 -3 -9 -7 -3 -1 -9 -6 -3 -3 -4 -0 -2 -1 -3 -9 -9 -1 -7 -9 -7 -9 -6 -1 -5 -6 -6 -9 -0 -4 -2 -2 -4 -3 -7 -6 -4 -1 -4 -2 -6 -1 -0 -2 -2 -1 -0 -2 -7 -2 -6 -0 -2 -0 -2 -0 -0 -5 -0 -3 -9 -0 -6 -6 -4 -1 -5 -9 -2 -4 -6 -4 -1 -1 -3 -0 -1 -1 -5 -0 -2 -9 -7 -3 -6 -8 -7 -8 -8 -7 -2 -6 -9 -4 -5 -7 -1 -3 -6 -0 -9 -9 -4 -6 -8 -6 -4 -1 -0 -3 -3 -0 -1 -8 -9 -5 -5 -7 -7 -3 -4 -6 -2 -9 -3 -0 -7 -6 -8 -8 -2 -4 -0 -6 -9 -8 -3 -9 -2 -0 -1 -6 -7 -7 -6 -4 -6 -5 -9 -6 -1 -3 -3 -5 -2 -1 -6 -4 -1 -9 -9 -6 -6 -6 -4 -5 -9 -4 -9 -9 -2 -2 -5 -1 -6 -2 -8 -7 -2 -8 -4 -7 -6 -1 -0 -1 -9 -0 -7 -4 -9 -0 -9 -4 -9 -0 -3 -6 -7 -4 -3 -7 -0 -2 -1 -5 -1 -4 -2 -4 -5 -2 -6 -6 -8 -8 -6 -7 -9 -1 -9 -1 -3 -2 -5 -9 -0 -9 -0 -1 -6 -9 -7 -7 -3 -0 -5 -3 -1 -9 -2 -6 -7 -9 -1 -0 -5 -1 -6 -8 -8 -6 -7 -3 -7 -2 -8 -9 -1 -0 -6 -1 -1 -6 -6 -9 -0 -1 -6 -9 -8 -1 -3 -7 -7 -8 -1 -4 -7 -0 -6 -0 -6 -4 -3 -1 -9 -6 -3 -0 -0 -2 -8 -9 -8 -1 -1 -8 -1 -3 -2 -3 -1 -0 -5 -9 -5 -0 -7 -1 -0 -6 -1 -5 -1 -1 -8 -2 -2 -6 -1 -7 -9 -7 -6 -7 -5 -1 -0 -6 -2 -7 -6 -4 -4 -4 -0 -8 -2 -0 -0 -6 -4 -8 -1 -9 -2 -9 -5 -1 -5 -1 -1 -4 -7 -0 -1 -2 -4 -6 -1 -9 -2 -9 -2 -9 -2 -6 -6 -5 -5 -5 -8 -5 -6 -1 -1 -6 -1 -2 -1 -9 -4 -7 -6 -7 -1 -0 -6 -4 -6 -5 -3 -3 -8 -0 -1 -1 -6 -0 -5 -1 -2 -1 -6 -4 -3 -9 -0 -4 -0 -3 -1 -4 -9 -2 -1 -7 -0 -9 -6 -8 -5 -8 -6 -0 -6 -7 -9 -9 -3 -1 -3 -9 -3 -1 -1 -2 -0 -0 -7 -7 -5 -1 -6 -0 -6 -7 -9 -3 -6 -2 -2 -2 -9 -9 -9 -9 -2 -7 -9 -2 -8 -1 -7 -7 -3 -7 -8 -7 -2 -5 -6 -1 -9 -7 -7 -7 -8 -9 -9 -7 -8 -9 -5 -2 -9 -5 -0 -7 -6 -1 -2 -6 -2 -7 -3 -5 -6 -9 -5 -8 -8 -2 -2 -9 -7 -9 -5 -1 -1 -1 -4 -5 -6 -1 -7 -0 -7 -9 -2 -7 -2 -3 -1 -5 -7 -1 -5 -1 -6 -0 -2 -6 -9 -9 -7 -9 -8 -7 -7 -7 -5 -6 -2 -9 -8 -8 -6 -7 -3 -1 -3 -9 -1 -2 -0 -2 -6 -5 -1 -0 -9 -9 -1 -6 -8 -5 -5 -6 -2 -3 -6 -1 -6 -6 -2 -0 -6 -0 -8 -1 -2 -8 -6 -4 -8 -5 -0 -4 -5 -0 -9 -7 -9 -2 -9 -2 -8 -5 -3 -5 -9 -7 -9 -5 -7 -3 -0 -2 -8 -0 -6 -6 -6 -9 -9 -3 -9 -2 -2 -3 -3 -7 -4 -5 -8 -5 -3 -6 -0 -5 -1 -2 -6 -9 -5 -5 -2 -7 -9 -1 -9 -3 -6 -8 -8 -2 -5 -8 -3 -9 -1 -6 -9 -6 -7 -5 -8 -5 -0 -8 -6 -7 -8 -1 -7 -1 -9 -3 -8 -8 -3 -9 -9 -8 -7 -6 -0 -5 -3 -0 -9 -9 -6 -8 -7 -9 -1 -2 -3 -2 -1 -5 -2 -9 -4 -4 -9 -3 -0 -0 -1 -1 -3 -1 -1 -2 -1 -6 -2 -7 -6 -0 -4 -4 -7 -0 -7 -0 -8 -7 -1 -3 -7 -8 -9 -0 -9 -0 -0 -1 -8 -8 -7 -4 -8 -3 -5 -9 -0 -3 -6 -3 -6 -3 -0 -9 -2 -6 -9 -3 -0 -5 -4 -5 -7 -7 -4 -2 -3 -9 -2 -1 -1 -0 -1 -9 -4 -2 -2 -1 -3 -2 -7 -3 -5 -1 -3 -0 -2 -1 -1 -7 -9 -1 -8 -9 -1 -6 -9 -7 -1 -8 -9 -9 -2 -0 -6 -1 -5 -2 -0 -9 -2 -5 -5 -3 -9 -0 -1 -0 -9 -6 -0 -9 -3 -7 -8 -0 -4 -0 -2 -6 -8 -2 -1 -9 -2 -1 -8 -6 -6 -1 -4 -8 -6 -2 -1 -3 -9 -8 -3 -7 -8 -7 -8 -7 -1 -5 -6 -4 -7 -5 -5 -4 -0 -8 -1 -6 -6 -3 -3 -7 -8 -8 -4 -3 -4 -3 -2 -1 -7 -0 -9 -4 -2 -8 -6 -8 -5 -1 -8 -4 -8 -1 -4 -3 -9 -1 -2 -1 -5 -3 -6 -7 -2 -4 -7 -6 -9 -1 -9 -8 -6 -8 -2 -6 -2 -0 -1 -1 -0 -6 -3 -9 -7 -3 -1 -9 -4 -6 -9 -7 -2 -7 -8 -1 -0 -5 -1 -2 -7 -6 -6 -3 -0 -4 -1 -9 -6 -3 -9 -1 -2 -4 -1 -3 -4 -0 -1 -8 -0 -2 -9 -2 -7 -9 -9 -1 -4 -7 -3 -2 -9 -9 -1 -3 -7 -8 -4 -9 -7 -9 -7 -1 -4 -4 -0 -0 -0 -3 -5 -8 -3 -0 -4 -1 -2 -8 -1 -0 -8 -8 -3 -4 -6 -9 -3 -2 -7 -2 -6 -8 -1 -0 -1 -8 -1 -3 -7 -4 -9 -1 -3 -5 -0 -3 -5 -4 -8 -6 -1 -9 -9 -6 -6 -6 -1 -9 -0 -3 -9 -8 -4 -6 -5 -6 -8 -9 -9 -5 -1 -8 -0 -2 -0 -3 -9 -5 -7 -0 -1 -0 -7 -2 -8 -1 -8 -3 -3 -7 -9 -6 -9 -9 -5 -7 -4 -6 -4 -9 -6 -0 -0 -4 -3 -5 -7 -1 -2 -1 -9 -2 -1 -3 -1 -9 -1 -8 -5 -8 -7 -9 -3 -6 -3 -6 -1 -7 -5 -8 -2 -6 -3 -7 -0 -5 -6 -7 -9 -6 -8 -6 -0 -9 -5 -9 -6 -1 -9 -5 -6 -7 -6 -2 -6 -5 -6 -6 -0 -4 -3 -9 -4 -3 -5 -0 -2 -6 -5 -0 -7 -6 -0 -6 -0 -5 -3 -6 -1 -9 -3 -8 -4 -4 -3 -4 -5 -4 -6 -0 -6 -1 -2 -0 -3 -9 -5 -0 -4 -1 -1 -3 -3 -9 -3 -3 -6 -4 -9 -0 -6 -9 -7 -9 -8 -5 -7 -9 -1 -4 -6 -5 -1 -8 -4 -9 -7 -1 -6 -8 -6 -7 -9 -4 -4 -0 -7 -7 -9 -1 -1 -6 -8 -0 -8 -3 -2 -7 -6 -7 -0 -1 -6 -5 -4 -5 -6 -2 -5 -3 -9 -5 -1 -3 -9 -6 -9 -2 -0 -6 -2 -7 -6 -0 -0 -3 -9 -1 -2 -9 -3 -0 -6 -1 -0 -9 -9 -6 -5 -1 -3 -6 -7 -1 -5 -1 -8 -1 -7 -3 -7 -9 -5 -2 -4 -9 -6 -8 -6 -6 -0 -8 -1 -7 -7 -1 -9 -0 -1 -4 -9 -1 -7 -3 -1 -6 -2 -2 -7 -2 -4 -1 -5 -6 -1 -5 -3 -2 -6 -9 -1 -7 -4 -5 -6 -5 -6 -3 -8 -1 -3 -9 -5 -6 -7 -1 -3 -3 -7 -1 -1 -8 -0 -6 -3 -9 -3 -3 -6 -2 -2 -0 -1 -0 -1 -1 -3 -7 -2 -9 -0 -3 -8 -8 -0 -1 -9 -5 -5 -2 -1 -3 -6 -0 -2 -7 -2 -9 -1 -5 -7 -1 -7 -4 -3 -9 -4 -4 -3 -2 -0 -0 -0 -3 -1 -1 -4 -3 -9 -2 -2 -2 -8 -6 -9 -4 -0 -4 -9 -1 -0 -7 -1 -2 -1 -6 -2 -4 -0 -4 -6 -0 -1 -1 -4 -2 -6 -2 -7 -7 -3 -4 -3 -9 -0 -1 -4 -8 -6 -2 -1 -1 -7 -3 -2 -9 -2 -2 -5 -2 -1 -0 -2 -5 -0 -0 -0 -9 -2 -7 -3 -0 -2 -1 -9 -0 -8 -5 -3 -8 -2 -2 -0 -2 -7 -8 -4 -0 -3 -0 -2 -2 -8 -0 -9 -2 -3 -0 -2 -9 -9 -7 -1 -4 -2 -2 -1 -6 -7 -6 -6 -3 -3 -6 -7 -3 -9 -1 -2 -3 -5 -0 -1 -0 -9 -7 -9 -0 -1 -5 -1 -4 -3 -6 -4 -8 -1 -2 -2 -6 -4 -2 -5 -8 -2 -6 -5 -8 -3 -1 -7 -4 -6 -0 -1 -5 -8 -1 -4 -0 -3 -6 -6 -1 -6 -2 -5 -9 -1 -5 -6 -6 -1 -4 -0 -3 -6 -0 -1 -6 -8 -9 -4 -7 -7 -7 -8 -8 -7 -5 -2 -7 -8 -1 -1 -9 -5 -4 -1 -0 -1 -3 -2 -3 -6 -8 -3 -1 -2 -7 -1 -7 -7 -0 -0 -1 -0 -0 -2 -0 -0 -7 -1 -7 -8 -6 -5 -7 -1 -6 -6 -9 -9 -9 -1 -3 -9 -0 -4 -9 -2 -8 -6 -2 -7 -4 -7 -5 -0 -3 -7 -5 -6 -6 -9 -0 -3 -5 -2 -8 -9 -8 -2 -2 -9 -7 -1 -7 -7 -2 -7 -3 -2 -2 -5 -4 -0 -2 -2 -8 -1 -1 -2 -9 -2 -3 -8 -1 -6 -9 -9 -4 -3 -9 -7 -9 -0 -7 -3 -5 -2 -3 -0 -1 -9 -9 -7 -9 -2 -7 -4 -7 -0 -6 -5 -1 -9 -5 -9 -7 -2 -2 -5 -6 -3 -5 -8 -2 -3 -3 -1 -4 -7 -3 -8 -4 -5 -7 -6 -1 -9 -0 -4 -8 -0 -6 -5 -6 -5 -2 -0 -5 -3 -1 -5 -1 -4 -1 -1 -1 -1 -5 -7 -1 -0 -4 -2 -9 -5 -5 -9 -3 -5 -2 -0 -0 -1 -0 -4 -2 -4 -3 -2 -7 -9 -4 -0 -1 -9 -9 -4 -9 -3 -2 -0 -8 -4 -1 -0 -9 -3 -4 -9 -6 -9 -0 -6 -1 -1 -2 -9 -7 -8 -7 -3 -7 -0 -1 -8 -6 -2 -5 -4 -8 -9 -1 -0 -2 -8 -7 -9 -4 -4 -7 -6 -9 -4 -1 -9 -5 -8 -3 -4 -2 -6 -7 -8 -7 -8 -7 -4 -9 -4 -7 -3 -6 -9 -1 -1 -1 -0 -1 -8 -1 -6 -9 -3 -3 -6 -9 -5 -8 -1 -9 -2 -3 -7 -9 -9 -2 -9 -8 -3 -4 -5 -1 -9 -9 -6 -1 -3 -5 -2 -9 -6 -5 -3 -5 -1 -5 -0 -2 -6 -8 -9 -9 -0 -6 -6 -7 -5 -8 -2 -0 -9 -5 -0 -1 -9 -7 -2 -3 -3 -0 -4 -9 -3 -1 -3 -9 -0 -3 -5 -4 -9 -4 -6 -8 -9 -6 -9 -3 -8 -6 -5 -0 -4 -8 -6 -0 -0 -9 -1 -4 -2 -5 -6 -3 -8 -0 -8 -8 -2 -4 -2 -7 -6 -9 -7 -8 -6 -9 -8 -6 -1 -5 -4 -3 -9 -9 -5 -0 -8 -2 -9 -1 -6 -9 -1 -0 -1 -8 -7 -6 -1 -6 -4 -1 -7 -5 -9 -1 -1 -2 -3 -9 -0 -7 -2 -2 -4 -1 -7 -7 -7 -8 -3 -5 -5 -6 -2 -1 -0 -8 -7 -7 -5 -1 -1 -8 -6 -5 -6 -6 -9 -8 -1 -7 -4 -9 -1 -6 -7 -3 -0 -7 -2 -1 -6 -8 -1 -3 -9 -0 -7 -5 -3 -2 -9 -0 -6 -1 -4 -0 -9 -7 -0 -6 -5 -5 -7 -0 -1 -5 -6 -1 -4 -8 -6 -8 -9 -5 -1 -0 -2 -2 -0 -7 -8 -2 -5 -1 -8 -3 -7 -6 -9 -1 -4 -9 -1 -0 -3 -3 -5 -9 -2 -7 -6 -3 -3 -8 -0 -0 -9 -7 -5 -5 -0 -3 -8 -7 -3 -1 -0 -7 -1 -5 -7 -0 -2 -5 -9 -2 -6 -1 -3 -1 -1 -3 -6 -6 -8 -4 -2 -3 -0 -1 -4 -4 -1 -1 -8 -4 -7 -6 -7 -5 -1 -9 -2 -0 -9 -1 -4 -3 -9 -4 -6 -9 -8 -5 -6 -8 -9 -7 -0 -0 -1 -0 -9 -7 -0 -2 -2 -7 -9 -6 -9 -5 -6 -1 -1 -1 -5 -8 -7 -9 -6 -2 -2 -2 -8 -5 -7 -1 -1 -1 -2 -9 -1 -8 -1 -3 -2 -1 -0 -6 -4 -7 -6 -5 -0 -1 -2 -8 -8 -4 -4 -3 -7 -4 -4 -9 -2 -8 -8 -6 -1 -5 -4 -5 -6 -8 -7 -0 -0 -1 -5 -4 -1 -5 -7 -3 -2 -0 -9 -9 -4 -9 -5 -0 -3 -6 -2 -3 -1 -7 -6 -0 -8 -2 -7 -7 -5 -8 -7 -4 -5 -0 -1 -9 -7 -4 -5 -0 -9 -8 -6 -3 -3 -1 -6 -1 -8 -0 -9 -9 -1 -1 -3 -7 -0 -0 -3 -0 -4 -9 -9 -8 -8 -0 -9 -0 -1 -6 -6 -6 -0 -2 -5 -7 -0 -6 -9 -7 -2 -2 -5 -3 -6 -6 -9 -2 -5 -4 -3 -5 -2 -4 -5 -4 -1 -7 -2 -3 -1 -9 -9 -2 -9 -0 -8 -1 -5 -7 -8 -6 -6 -8 -3 -2 -6 -7 -0 -6 -0 -2 -2 -3 -0 -6 -3 -3 -4 -2 -1 -4 -3 -3 -0 -0 -3 -2 -4 -1 -5 -9 -2 -4 -2 -5 -8 -7 -9 -9 -1 -5 -0 -0 -9 -0 -8 -8 -0 -9 -8 -6 -2 -3 -2 -0 -6 -3 -3 -1 -9 -2 -0 -5 -2 -8 -9 -4 -2 -6 -0 -2 -0 -6 -5 -3 -4 -1 -2 -2 -4 -9 -4 -3 -2 -1 -9 -1 -6 -1 -2 -3 -4 -0 -1 -9 -4 -0 -0 -4 -8 -1 -9 -2 -5 -3 -4 -3 -7 -0 -7 -9 -7 -9 -5 -9 -7 -7 -0 -4 -2 -1 -1 -8 -5 -0 -4 -9 -8 -8 -2 -4 -1 -4 -1 -4 -1 -0 -9 -9 -5 -6 -9 -9 -1 -2 -6 -0 -3 -0 -3 -3 -0 -4 -0 -1 -0 -8 -4 -9 -3 -7 -1 -4 -1 -7 -6 -0 -7 -7 -1 -5 -0 -3 -6 -0 -2 -8 -5 -3 -5 -7 -7 -2 -9 -6 -7 -8 -1 -5 -7 -3 -1 -7 -3 -1 -8 -0 -1 -0 -4 -3 -2 -7 -9 -7 -9 -3 -6 -2 -3 -4 -1 -3 -0 -9 -9 -2 -6 -4 -0 -0 -7 -5 -1 -8 -3 -8 -1 -6 -5 -8 -9 -2 -2 -0 -7 -1 -6 -2 -1 -6 -8 -4 -3 -5 -9 -1 -0 -5 -3 -1 -9 -2 -1 -8 -1 -3 -6 -0 -1 -2 -4 -1 -3 -7 -4 -9 -4 -2 -0 -6 -3 -5 -0 -4 -3 -6 -1 -7 -6 -2 -7 -1 -7 -0 -6 -9 -6 -5 -1 -3 -6 -8 -1 -9 -0 -6 -6 -9 -3 -6 -8 -2 -9 -0 -6 -1 -8 -1 -1 -0 -0 -9 -9 -9 -4 -8 -4 -1 -6 -4 -9 -1 -8 -9 -2 -3 -4 -6 -1 -0 -1 -6 -7 -9 -0 -0 -8 -5 -4 -2 -5 -2 -8 -4 -6 -9 -7 -1 -4 -3 -5 -2 -9 -3 -3 -5 -3 -0 -0 -1 -9 -2 -5 -3 -7 -6 -5 -9 -6 -5 -0 -9 -1 -3 -8 -5 -7 -7 -0 -7 -7 -1 -5 -6 -7 -0 -4 -3 -0 -0 -0 -0 -7 -6 -8 -2 -6 -7 -1 -7 -1 -0 -2 -3 -5 -1 -8 -5 -4 -7 -6 -2 -6 -6 -8 -3 -8 -5 -1 -5 -2 -6 -5 -1 -5 -8 -3 -5 -5 -3 -2 -3 -5 -5 -8 -6 -7 -0 -3 -8 -8 -4 -2 -6 -4 -5 -8 -3 -0 -9 -1 -1 -3 -0 -9 -6 -7 -8 -2 -5 -3 -6 -2 -0 -2 -5 -1 -2 -9 -9 -0 -2 -5 -5 -6 -1 -4 -1 -3 -1 -5 -5 -0 -1 -9 -3 -9 -5 -0 -7 -9 -8 -3 -0 -1 -3 -3 -8 -1 -3 -5 -7 -0 -1 -6 -4 -8 -5 -0 -6 -0 -4 -5 -8 -2 -1 -5 -4 -0 -1 -4 -1 -7 -3 -9 -2 -9 -1 -2 -1 -7 -6 -6 -1 -5 -9 -8 -9 -0 -2 -3 -1 -7 -3 -1 -5 -2 -7 -3 -2 -6 -9 -7 -4 -0 -5 -1 -5 -9 -1 -0 -9 -4 -5 -9 -8 -7 -1 -3 -3 -2 -4 -1 -1 -8 -0 -5 -2 -8 -9 -0 -9 -7 -0 -9 -9 -2 -7 -6 -1 -7 -1 -6 -0 -2 -9 -9 -9 -7 -8 -2 -4 -0 -9 -3 -5 -9 -4 -2 -0 -3 -2 -0 -2 -9 -4 -8 -5 -5 -6 -9 -6 -8 -4 -7 -6 -7 -4 -9 -4 -2 -1 -0 -8 -1 -7 -6 -0 -1 -9 -3 -6 -5 -5 -0 -7 -1 -3 -6 -9 -3 -3 -4 -8 -4 -7 -9 -1 -2 -9 -6 -7 -4 -8 -9 -3 -9 -5 -6 -7 -9 -2 -2 -1 -8 -3 -2 -7 -1 -7 -1 -2 -8 -7 -9 -8 -0 -9 -4 -0 -0 -2 -2 -4 -2 -0 -7 -6 -3 -2 -7 -4 -1 -2 -7 -4 -9 -2 -1 -7 -5 -8 -0 -5 -7 -9 -7 -1 -5 -5 -4 -2 -4 -7 -9 -9 -6 -4 -5 -4 -9 -1 -9 -6 -5 -6 -2 -8 -6 -8 -3 -8 -9 -6 -8 -8 -6 -4 -0 -2 -6 -1 -3 -8 -9 -8 -7 -7 -7 -8 -0 -7 -9 -5 -0 -3 -7 -4 -6 -4 -7 -2 -9 -6 -4 -0 -4 -6 -1 -8 -4 -9 -9 -4 -3 -6 -9 -0 -4 -1 -8 -5 -7 -8 -5 -2 -8 -8 -7 -0 -5 -0 -7 -2 -3 -4 -7 -8 -1 -5 -5 -9 -5 -2 -5 -0 -5 -6 -9 -7 -4 -1 -1 -9 -1 -9 -9 -4 -8 -4 -3 -7 -6 -2 -0 -1 -8 -9 -6 -7 -9 -5 -7 -5 -3 -1 -6 -0 -3 -2 -4 -5 -1 -5 -1 -5 -3 -5 -8 -5 -8 -5 -2 -7 -0 -1 -1 -1 -9 -0 -9 -9 -2 -0 -7 -5 -1 -3 -4 -7 -8 -0 -1 -2 -9 -3 -1 -6 -2 -0 -5 -0 -1 -6 -1 -9 -7 -7 -8 -6 -8 -4 -0 -7 -1 -0 -1 -3 -4 -9 -0 -9 -4 -5 -1 -6 -9 -4 -6 -6 -6 -1 -1 -3 -5 -8 -7 -4 -8 -6 -9 -8 -1 -1 -1 -3 -3 -5 -6 -5 -6 -2 -8 -7 -9 -1 -1 -9 -9 -0 -6 -6 -2 -3 -8 -3 -0 -0 -5 -0 -9 -2 -1 -3 -3 -5 -1 -8 -9 -9 -1 -5 -6 -9 -1 -7 -2 -9 -1 -6 -3 -5 -0 -7 -7 -6 -5 -1 -8 -1 -3 -4 -5 -0 -7 -4 -2 -8 -0 -4 -5 -1 -9 -7 -4 -2 -8 -8 -5 -8 -6 -8 -7 -9 -9 -7 -9 -4 -2 -6 -9 -1 -9 -9 -0 -6 -8 -3 -0 -1 -4 -6 -6 -8 -1 -9 -4 -3 -7 -2 -8 -5 -1 -9 -6 -8 -0 -0 -1 -7 -9 -4 -9 -6 -0 -7 -3 -9 -7 -2 -7 -4 -2 -0 -5 -2 -6 -4 -1 -7 -3 -0 -4 -3 -1 -6 -1 -4 -9 -2 -1 -0 -3 -3 -9 -0 -9 -6 -6 -0 -2 -7 -3 -0 -5 -8 -8 -5 -3 -5 -0 -8 -0 -7 -3 -3 -2 -5 -1 -3 -6 -5 -9 -7 -2 -2 -9 -0 -8 -8 -0 -5 -0 -8 -0 -4 -1 -6 -7 -7 -8 -1 -0 -2 -6 -4 -6 -8 -8 -6 -6 -4 -9 -4 -5 -5 -6 -3 -1 -7 -6 -1 -9 -9 -0 -6 -6 -5 -2 -0 -8 -9 -3 -1 -8 -1 -0 -3 -0 -6 -6 -8 -6 -2 -3 -2 -9 -2 -0 -6 -0 -2 -1 -2 -6 -6 -1 -7 -7 -0 -2 -9 -4 -1 -0 -0 -7 -5 -8 -5 -6 -1 -7 -0 -6 -6 -5 -9 -3 -6 -4 -2 -1 -1 -7 -1 -5 -9 -3 -3 -7 -6 -1 -6 -2 -1 -2 -5 -7 -0 -5 -2 -6 -0 -9 -1 -0 -5 -5 -2 -4 -6 -3 -0 -9 -4 -9 -4 -7 -0 -0 -4 -0 -9 -2 -7 -1 -1 -2 -1 -1 -6 -3 -2 -5 -5 -1 -8 -2 -0 -3 -8 -4 -1 -6 -8 -5 -8 -5 -3 -5 -8 -6 -7 -1 -6 -1 -9 -3 -9 -3 -9 -3 -1 -9 -8 -8 -3 -1 -7 -8 -6 -5 -4 -6 -0 -0 -2 -0 -0 -0 -2 -6 -7 -5 -1 -0 -0 -0 -9 -3 -8 -0 -9 -5 -9 -4 -2 -3 -2 -7 -2 -0 -2 -6 -2 -2 -8 -8 -8 -5 -1 -2 -2 -6 -7 -0 -2 -2 -1 -4 -3 -4 -1 -9 -7 -0 -5 -6 -5 -1 -8 -5 -3 -3 -9 -0 -6 -6 -9 -2 -1 -0 -4 -8 -4 -5 -7 -9 -2 -2 -2 -1 -1 -4 -4 -7 -8 -6 -8 -6 -5 -5 -8 -1 -8 -2 -9 -1 -9 -7 -2 -4 -4 -4 -9 -9 -3 -0 -5 -5 -5 -5 -2 -7 -0 -0 -1 -3 -5 -3 -0 -0 -0 -3 -1 -4 -0 -2 -6 -9 -7 -6 -9 -6 -6 -9 -0 -2 -2 -4 -1 -9 -2 -7 -2 -5 -9 -4 -6 -2 -7 -6 -8 -9 -1 -8 -8 -0 -2 -4 -9 -9 -1 -7 -1 -9 -9 -2 -1 -4 -5 -2 -7 -6 -0 -0 -3 -0 -6 -6 -8 -0 -0 -3 -6 -7 -8 -0 -8 -6 -4 -5 -8 -1 -5 -0 -6 -6 -9 -5 -1 -6 -4 -3 -0 -7 -2 -5 -5 -9 -9 -5 -6 -9 -0 -1 -9 -2 -9 -5 -6 -4 -9 -7 -6 -2 -8 -0 -4 -1 -8 -2 -1 -3 -4 -1 -7 -7 -2 -9 -3 -8 -6 -3 -2 -2 -6 -3 -5 -7 -1 -1 -1 -7 -7 -5 -2 -9 -7 -9 -1 -5 -6 -4 -4 -4 -1 -9 -0 -5 -4 -3 -4 -6 -6 -3 -8 -6 -7 -4 -9 -5 -9 -0 -0 -0 -8 -6 -4 -2 -3 -0 -9 -8 -5 -9 -8 -6 -7 -6 -1 -4 -0 -1 -6 -1 -4 -5 -6 -1 -1 -9 -1 -5 -7 -5 -9 -2 -5 -1 -0 -6 -7 -1 -1 -6 -4 -0 -5 -6 -0 -8 -0 -7 -4 -9 -9 -0 -2 -2 -0 -3 -0 -5 -1 -0 -1 -1 -2 -8 -2 -6 -2 -6 -2 -0 -2 -9 -7 -3 -3 -8 -5 -0 -6 -6 -9 -5 -3 -2 -7 -3 -4 -7 -7 -5 -8 -1 -1 -6 -0 -5 -7 -5 -9 -5 -0 -4 -3 -7 -6 -3 -5 -4 -5 -1 -1 -9 -4 -8 -3 -7 -3 -0 -9 -4 -7 -8 -4 -8 -1 -1 -0 -5 -6 -7 -9 -5 -6 -1 -0 -6 -0 -2 -1 -7 -9 -0 -3 -2 -8 -7 -0 -1 -3 -4 -9 -0 -7 -6 -1 -3 -9 -2 -3 -1 -4 -1 -1 -7 -4 -4 -5 -1 -2 -8 -9 -6 -6 -5 -4 -0 -6 -1 -3 -5 -2 -8 -1 -9 -0 -5 -3 -3 -9 -2 -9 -1 -7 -4 -5 -0 -5 -1 -9 -1 -1 -9 -9 -9 -6 -6 -1 -4 -5 -4 -8 -7 -6 -1 -1 -0 -4 -6 -2 -9 -9 -5 -3 -6 -4 -3 -3 -8 -2 -2 -1 -5 -8 -7 -5 -2 -8 -0 -7 -2 -5 -5 -6 -4 -8 -7 -3 -8 -2 -1 -3 -9 -5 -0 -4 -0 -6 -5 -5 -0 -0 -6 -7 -7 -1 -1 -1 -5 -6 -6 -5 -1 -4 -9 -5 -0 -4 -9 -1 -7 -7 -4 -6 -9 -3 -0 -0 -7 -8 -0 -8 -3 -0 -5 -8 -5 -1 -6 -0 -9 -0 -9 -5 -3 -0 -1 -7 -1 -1 -4 -4 -0 -4 -1 -7 -1 -5 -5 -4 -5 -6 -8 -3 -3 -1 -1 -8 -0 -9 -8 -2 -7 -2 -9 -8 -9 -5 -4 -8 -2 -2 -3 -2 -6 -8 -9 -1 -1 -9 -5 -9 -1 -7 -2 -7 -9 -1 -2 -9 -7 -5 -5 -5 -7 -4 -3 -5 -9 -7 -8 -0 -6 -1 -4 -8 -2 -3 -1 -8 -2 -9 -7 -9 -7 -3 -3 -2 -9 -2 -7 -6 -1 -9 -9 -2 -1 -2 -5 -8 -1 -6 -3 -0 -9 -1 -2 -6 -5 -5 -8 -4 -2 -6 -1 -6 -1 -0 -4 -9 -0 -1 -4 -1 -2 -1 -6 -0 -7 -6 -1 -0 -0 -1 -8 -3 -0 -6 -7 -0 -3 -2 -0 -1 -7 -8 -4 -4 -6 -1 -6 -2 -0 -0 -3 -9 -9 -8 -7 -5 -8 -0 -1 -0 -0 -0 -5 -6 -2 -2 -5 -3 -8 -8 -1 -9 -2 -7 -4 -0 -5 -3 -8 -3 -6 -9 -9 -3 -4 -8 -9 -4 -3 -2 -9 -2 -3 -7 -3 -7 -7 -7 -0 -9 -9 -4 -2 -3 -6 -6 -7 -9 -3 -9 -7 -1 -4 -9 -0 -9 -9 -8 -0 -0 -9 -9 -7 -3 -9 -4 -4 -9 -2 -1 -9 -9 -6 -9 -1 -9 -6 -4 -7 -7 -7 -2 -7 -6 -2 -9 -6 -6 -7 -3 -9 -8 -1 -0 -9 -2 -8 -0 -3 -1 -4 -5 -2 -1 -9 -4 -4 -1 -0 -9 -1 -9 -7 -4 -5 -9 -3 -8 -5 -7 -0 -1 -4 -1 -8 -1 -6 -6 -9 -6 -8 -8 -1 -6 -2 -7 -8 -0 -2 -0 -4 -5 -5 -8 -1 -7 -6 -5 -4 -6 -0 -2 -2 -1 -5 -7 -2 -4 -6 -4 -4 -9 -2 -2 -7 -6 -1 -7 -1 -6 -3 -9 -7 -5 -1 -7 -9 -2 -2 -5 -7 -3 -5 -7 -6 -2 -8 -7 -2 -8 -9 -9 -2 -9 -2 -4 -4 -1 -6 -0 -6 -9 -6 -5 -6 -9 -6 -1 -2 -2 -5 -0 -9 -4 -1 -9 -4 -3 -6 -9 -6 -5 -7 -0 -3 -0 -0 -2 -7 -0 -7 -8 -7 -2 -7 -5 -8 -0 -7 -2 -9 -6 -2 -0 -9 -7 -3 -5 -0 -5 -9 -0 -9 -6 -9 -1 -9 -1 -0 -0 -8 -8 -9 -8 -3 -9 -7 -7 -8 -2 -5 -4 -7 -5 -5 -7 -1 -1 -9 -2 -7 -9 -5 -7 -6 -1 -2 -2 -9 -1 -4 -6 -5 -4 -4 -8 -4 -7 -1 -2 -0 -7 -6 -7 -6 -7 -1 -5 -2 -9 -2 -7 -6 -6 -6 -1 -1 -4 -6 -9 -4 -2 -1 -0 -5 -1 -5 -7 -4 -6 -2 -3 -5 -2 -5 -9 -1 -7 -3 -8 -0 -1 -6 -5 -9 -7 -7 -0 -9 -6 -3 -8 -9 -0 -1 -2 -1 -1 -3 -5 -9 -9 -8 -7 -1 -9 -9 -3 -5 -7 -1 -4 -4 -7 -4 -3 -9 -1 -9 -1 -3 -7 -3 -1 -4 -7 -3 -5 -6 -5 -6 -1 -8 -9 -4 -7 -1 -1 -8 -2 -6 -4 -6 -6 -0 -6 -2 -3 -3 -4 -3 -5 -6 -8 -2 -4 -3 -8 -0 -1 -0 -9 -3 -4 -2 -3 -0 -2 -5 -8 -1 -7 -5 -0 -9 -7 -7 -7 -1 -0 -4 -9 -4 -1 -6 -7 -4 -4 -6 -0 -7 -2 -2 -3 -9 -1 -1 -2 -2 -2 -3 -8 -0 -5 -2 -6 -2 -1 -1 -8 -7 -8 -2 -3 -8 -7 -1 -6 -3 -7 -0 -5 -6 -6 -7 -4 -2 -2 -1 -7 -3 -4 -3 -9 -8 -8 -0 -2 -3 -9 -1 -3 -6 -3 -8 -7 -9 -2 -6 -3 -6 -9 -2 -2 -5 -9 -3 -7 -2 -3 -6 -9 -1 -9 -6 -4 -5 -6 -5 -0 -7 -3 -9 -9 -1 -6 -9 -1 -6 -9 -3 -5 -2 -2 -7 -9 -7 -2 -9 -0 -9 -8 -2 -1 -9 -1 -2 -5 -0 -9 -0 -5 -3 -8 -9 -5 -8 -6 -1 -9 -4 -1 -6 -6 -9 -6 -2 -7 -3 -8 -2 -4 -9 -1 -6 -4 -1 -1 -2 -3 -7 -5 -5 -2 -5 -3 -2 -1 -5 -8 -0 -4 -9 -2 -4 -6 -2 -8 -9 -9 -5 -8 -0 -5 -0 -0 -6 -6 -2 -6 -2 -0 -7 -1 -2 -8 -2 -9 -1 -6 -4 -3 -0 -0 -1 -5 -9 -3 -1 -0 -2 -5 -6 -8 -4 -4 -3 -4 -9 -7 -6 -6 -8 -4 -8 -3 -3 -8 -4 -1 -8 -2 -5 -5 -2 -9 -0 -0 -4 -1 -5 -7 -7 -3 -3 -6 -2 -6 -5 -1 -7 -3 -1 -7 -7 -9 -8 -7 -3 -3 -3 -1 -6 -1 -9 -5 -9 -3 -0 -0 -2 -0 -8 -0 -0 -2 -5 -5 -8 -5 -9 -7 -8 -9 -1 -5 -9 -7 -9 -7 -3 -1 -4 -3 -8 -4 -0 -7 -0 -6 -0 -9 -8 -1 -5 -3 -5 -6 -8 -7 -9 -1 -4 -4 -0 -2 -0 -4 -5 -5 -8 -8 -8 -9 -6 -6 -5 -1 -5 -7 -7 -5 -2 -2 -2 -3 -8 -6 -4 -8 -4 -1 -2 -7 -5 -5 -0 -4 -6 -6 -1 -4 -4 -6 -5 -5 -5 -9 -4 -6 -1 -3 -0 -2 -9 -5 -2 -3 -3 -2 -8 -1 -5 -6 -3 -4 -6 -4 -6 -3 -0 -0 -5 -5 -0 -7 -9 -1 -3 -1 -4 -8 -7 -5 -8 -0 -0 -0 -0 -6 -9 -7 -9 -9 -9 -0 -2 -4 -0 -7 -6 -1 -1 -4 -5 -3 -0 -8 -7 -8 -1 -3 -4 -1 -5 -2 -3 -0 -7 -1 -0 -3 -8 -5 -0 -3 -1 -5 -4 -5 -3 -6 -1 -6 -6 -1 -4 -7 -3 -7 -8 -6 -0 -5 -6 -6 -9 -5 -5 -2 -2 -6 -1 -5 -6 -0 -3 -2 -6 -6 -1 -5 -9 -5 -4 -6 -1 -1 -7 -2 -0 -5 -8 -1 -0 -4 -8 -6 -1 -9 -5 -1 -9 -6 -6 -7 -6 -7 -3 -1 -1 -1 -6 -4 -8 -1 -4 -4 -1 -4 -1 -1 -7 -9 -6 -3 -8 -6 -6 -6 -2 -5 -9 -4 -5 -1 -6 -6 -3 -0 -7 -9 -9 -6 -1 -1 -5 -1 -8 -1 -6 -9 -2 -7 -7 -0 -1 -9 -3 -9 -3 -2 -4 -9 -8 -7 -7 -1 -1 -6 -9 -5 -3 -5 -2 -8 -8 -9 -2 -8 -3 -9 -0 -8 -6 -6 -5 -0 -6 -7 -8 -9 -7 -4 -2 -7 -2 -8 -0 -0 -4 -2 -9 -0 -1 -9 -9 -9 -1 -7 -0 -7 -0 -3 -1 -6 -8 -1 -9 -4 -0 -7 -0 -9 -8 -1 -8 -8 -1 -2 -6 -5 -1 -0 -2 -6 -0 -3 -7 -0 -5 -3 -7 -7 -0 -5 -5 -2 -5 -1 -2 -7 -2 -7 -5 -6 -7 -6 -2 -4 -0 -1 -8 -6 -6 -9 -4 -6 -6 -2 -4 -4 -0 -1 -7 -9 -1 -8 -3 -3 -1 -4 -5 -2 -2 -7 -4 -1 -7 -4 -8 -9 -6 -8 -7 -8 -7 -0 -9 -4 -0 -2 -5 -0 -3 -6 -9 -4 -1 -0 -1 -2 -8 -1 -6 -0 -1 -2 -6 -3 -3 -2 -0 -6 -9 -2 -1 -3 -2 -8 -8 -0 -6 -1 -1 -8 -7 -4 -8 -3 -1 -9 -5 -5 -1 -8 -5 -0 -5 -9 -9 -5 -4 -5 -7 -3 -5 -7 -8 -0 -2 -1 -4 -0 -9 -1 -7 -9 -1 -6 -7 -1 -3 -5 -4 -4 -4 -0 -3 -5 -1 -4 -2 -1 -4 -0 -1 -1 -7 -5 -7 -1 -3 -3 -0 -4 -9 -4 -6 -8 -2 -9 -5 -1 -9 -5 -0 -8 -2 -5 -4 -3 -6 -7 -2 -5 -3 -6 -0 -1 -4 -9 -3 -6 -6 -5 -1 -9 -3 -0 -3 -8 -9 -7 -1 -3 -0 -5 -7 -9 -0 -4 -5 -9 -8 -2 -8 -3 -1 -5 -8 -3 -7 -5 -0 -3 -5 -4 -4 -2 -5 -9 -6 -6 -0 -1 -4 -1 -2 -6 -5 -0 -3 -8 -3 -0 -1 -1 -2 -9 -6 -1 -1 -0 -7 -2 -8 -4 -7 -2 -1 -6 -1 -8 -6 -7 -7 -6 -3 -2 -4 -1 -4 -5 -8 -3 -5 -4 -8 -4 -6 -6 -1 -7 -5 -6 -1 -3 -2 -2 -7 -0 -0 -2 -9 -1 -3 -3 -3 -3 -9 -3 -4 -1 -2 -6 -8 -1 -9 -5 -4 -7 -9 -0 -7 -2 -9 -9 -1 -4 -0 -6 -7 -8 -7 -4 -7 -1 -9 -4 -9 -6 -5 -1 -9 -3 -6 -6 -5 -2 -8 -3 -8 -2 -4 -0 -6 -0 -1 -5 -9 -0 -1 -6 -5 -2 -3 -0 -3 -0 -0 -8 -4 -5 -0 -5 -3 -0 -2 -3 -1 -2 -4 -3 -0 -2 -0 -7 -9 -3 -3 -9 -6 -5 -9 -8 -1 -8 -0 -6 -5 -1 -9 -5 -1 -7 -1 -9 -6 -2 -1 -1 -0 -5 -6 -4 -1 -9 -5 -3 -4 -5 -3 -8 -5 -3 -7 -2 -2 -2 -9 -8 -3 -0 -6 -7 -6 -2 -8 -6 -2 -1 -5 -7 -2 -1 -2 -3 -9 -4 -1 -9 -2 -8 -4 -6 -7 -8 -4 -9 -9 -4 -5 -1 -2 -0 -2 -9 -6 -1 -5 -0 -9 -5 -4 -7 -5 -8 -1 -5 -1 -1 -0 -5 -4 -2 -0 -0 -9 -0 -2 -7 -7 -5 -2 -5 -7 -6 -3 -7 -5 -4 -0 -8 -6 -3 -7 -3 -1 -6 -2 -4 -4 -4 -0 -5 -1 -8 -8 -3 -4 -5 -0 -2 -2 -0 -1 -1 -6 -1 -4 -3 -1 -5 -9 -9 -2 -5 -0 -0 -2 -4 -2 -8 -2 -8 -4 -9 -4 -4 -8 -0 -5 -8 -5 -9 -9 -4 -4 -9 -2 -4 -8 -3 -0 -9 -8 -7 -6 -2 -4 -2 -6 -2 -2 -7 -1 -1 -0 -2 -9 -9 -0 -5 -4 -7 -0 -5 -9 -4 -1 -5 -6 -6 -8 -1 -2 -4 -3 -3 -2 -9 -7 -1 -4 -9 -6 -9 -0 -2 -4 -4 -5 -7 -8 -9 -4 -2 -4 -1 -7 -8 -2 -8 -0 -1 -2 -9 -9 -7 -0 -1 -2 -6 -9 -4 -2 -1 -4 -5 -0 -8 -6 -1 -9 -5 -1 -6 -2 -1 -8 -0 -5 -1 -9 -9 -6 -6 -8 -1 -1 -7 -9 -4 -7 -7 -3 -4 -6 -0 -6 -3 -0 -6 -3 -0 -1 -3 -2 -6 -3 -2 -0 -5 -9 -1 -3 -9 -0 -2 -0 -5 -8 -9 -6 -6 -5 -2 -9 -7 -6 -0 -7 -9 -1 -3 -9 -1 -7 -6 -4 -9 -7 -6 -0 -0 -4 -8 -4 -9 -8 -3 -5 -1 -7 -7 -1 -4 -1 -6 -3 -9 -7 -6 -6 -1 -9 -4 -0 -0 -4 -4 -8 -3 -1 -7 -5 -8 -3 -7 -4 -1 -0 -3 -2 -9 -3 -2 -2 -6 -0 -9 -9 -8 -3 -1 -8 -6 -4 -2 -2 -1 -7 -3 -1 -9 -5 -0 -6 -8 -1 -7 -8 -3 -7 -6 -7 -7 -3 -9 -2 -4 -5 -7 -7 -9 -0 -9 -1 -8 -1 -8 -9 -4 -1 -9 -9 -6 -1 -7 -5 -3 -5 -3 -1 -8 -0 -0 -1 -0 -3 -6 -6 -1 -9 -9 -0 -1 -0 -2 -0 -6 -7 -7 -5 -3 -1 -8 -9 -7 -2 -4 -6 -2 -5 -0 -6 -5 -6 -8 -3 -4 -1 -1 -4 -6 -8 -7 -1 -8 -6 -8 -1 -2 -3 -3 -2 -3 -3 -6 -8 -2 -7 -6 -9 -8 -0 -9 -7 -7 -7 -8 -3 -1 -2 -3 -1 -4 -3 -6 -4 -8 -3 -1 -3 -6 -9 -6 -9 -0 -3 -9 -0 -7 -7 -3 -0 -0 -9 -3 -5 -7 -9 -8 -6 -0 -7 -7 -2 -8 -7 -9 -1 -2 -5 -6 -0 -7 -8 -1 -0 -3 -6 -9 -9 -5 -0 -3 -0 -1 -1 -6 -2 -5 -9 -5 -4 -0 -5 -5 -1 -2 -7 -6 -5 -3 -0 -5 -6 -9 -0 -7 -8 -1 -7 -1 -8 -7 -2 -7 -9 -7 -3 -2 -1 -2 -8 -4 -9 -2 -1 -3 -1 -8 -1 -6 -2 -7 -3 -9 -9 -4 -1 -6 -3 -1 -1 -7 -5 -3 -5 -2 -2 -9 -7 -1 -3 -9 -1 -1 -1 -8 -1 -6 -2 -6 -6 -1 -8 -2 -9 -7 -0 -3 -5 -7 -8 -7 -8 -7 -9 -3 -7 -1 -8 -5 -4 -7 -5 -3 -0 -5 -9 -7 -0 -7 -7 -4 -4 -5 -8 -9 -2 -9 -7 -5 -1 -4 -9 -9 -6 -4 -2 -0 -2 -6 -2 -2 -8 -4 -1 -6 -1 -2 -2 -1 -3 -1 -2 -4 -6 -4 -3 -5 -5 -5 -1 -0 -1 -1 -9 -1 -7 -2 -6 -9 -6 -5 -2 -5 -4 -8 -9 -3 -4 -8 -9 -7 -3 -5 -6 -5 -9 -8 -5 -7 -0 -4 -5 -1 -0 -1 -6 -9 -2 -1 -9 -7 -0 -9 -3 -1 -6 -3 -6 -0 -5 -2 -6 -5 -7 -9 -0 -2 -0 -8 -4 -0 -9 -9 -6 -0 -7 -5 -0 -1 -9 -6 -1 -1 -2 -7 -0 -3 -3 -8 -9 -9 -8 -4 -5 -4 -7 -9 -8 -6 -9 -8 -3 -0 -9 -6 -7 -9 -3 -5 -8 -1 -2 -7 -8 -7 -1 -6 -8 -3 -1 -6 -8 -7 -6 -9 -1 -5 -9 -0 -9 -4 -3 -3 -3 -4 -1 -9 -3 -0 -5 -2 -0 -6 -1 -6 -7 -9 -0 -4 -5 -4 -3 -5 -9 -4 -8 -7 -2 -8 -2 -6 -7 -9 -7 -6 -4 -6 -3 -4 -5 -7 -4 -2 -2 -9 -6 -9 -0 -5 -0 -0 -3 -3 -5 -3 -7 -6 -2 -2 -4 -9 -0 -5 -3 -1 -8 -5 -9 -9 -7 -1 -4 -3 -6 -7 -8 -1 -6 -4 -1 -4 -9 -7 -1 -3 -0 -8 -7 -8 -7 -1 -6 -9 -9 -8 -3 -1 -6 -8 -5 -0 -8 -4 -1 -6 -8 -1 -9 -4 -3 -8 -4 -0 -9 -9 -4 -9 -3 -7 -2 -8 -0 -4 -3 -7 -4 -4 -6 -5 -3 -0 -5 -3 -1 -4 -6 -5 -5 -9 -3 -1 -1 -3 -5 -0 -9 -2 -3 -5 -9 -2 -4 -3 -1 -0 -7 -7 -5 -6 -0 -4 -8 -8 -2 -0 -3 -7 -7 -0 -8 -3 -8 -2 -0 -0 -9 -5 -7 -2 -0 -1 -1 -3 -9 -2 -4 -4 -1 -4 -9 -2 -9 -1 -1 -9 -0 -2 -7 -9 -7 -9 -6 -7 -7 -7 -6 -7 -9 -4 -7 -1 -1 -6 -1 -1 -1 -1 -6 -3 -1 -1 -5 -6 -1 -3 -8 -1 -6 -9 -3 -9 -9 -5 -0 -5 -9 -6 -3 -0 -2 -2 -2 -4 -2 -0 -6 -7 -7 -0 -4 -7 -3 -5 -8 -7 -4 -0 -7 -4 -2 -4 -2 -9 -0 -6 -0 -4 -4 -7 -8 -0 -9 -9 -6 -1 -6 -6 -9 -9 -1 -3 -8 -0 -9 -4 -4 -9 -0 -0 -8 -1 -1 -0 -2 -5 -2 -0 -9 -2 -3 -6 -2 -0 -5 -9 -2 -9 -4 -1 -5 -1 -9 -1 -6 -4 -2 -1 -5 -9 -6 -0 -4 -4 -1 -3 -3 -3 -0 -4 -1 -5 -6 -1 -2 -0 -7 -8 -6 -4 -1 -2 -8 -4 -4 -8 -2 -1 -1 -9 -5 -1 -9 -0 -2 -7 -1 -6 -0 -7 -4 -4 -4 -5 -1 -7 -9 -6 -4 -5 -6 -9 -1 -4 -7 -9 -7 -8 -0 -8 -6 -9 -2 -7 -1 -2 -8 -1 -1 -9 -5 -8 -8 -6 -0 -7 -6 -4 -6 -3 -2 -6 -0 -9 -1 -6 -5 -2 -7 -3 -9 -7 -1 -0 -6 -9 -7 -6 -4 -0 -5 -0 -9 -7 -1 -3 -6 -4 -4 -9 -7 -7 -4 -2 -2 -1 -1 -5 -3 -5 -9 -7 -9 -3 -4 -8 -7 -7 -1 -1 -9 -9 -4 -4 -3 -0 -3 -9 -8 -1 -6 -4 -0 -6 -2 -9 -0 -6 -3 -6 -6 -6 -5 -1 -0 -9 -3 -6 -3 -8 -0 -1 -2 -0 -3 -2 -5 -7 -9 -1 -9 -8 -9 -4 -8 -9 -8 -8 -9 -1 -5 -1 -1 -6 -7 -0 -2 -8 -7 -4 -5 -5 -4 -6 -8 -1 -4 -0 -9 -4 -3 -7 -9 -3 -0 -2 -9 -6 -3 -3 -1 -2 -3 -4 -6 -7 -9 -3 -6 -7 -9 -3 -3 -1 -2 -4 -5 -9 -9 -0 -1 -9 -7 -6 -8 -7 -8 -0 -6 -7 -9 -6 -7 -1 -2 -7 -8 -6 -0 -8 -1 -1 -7 -7 -3 -5 -3 -7 -6 -4 -0 -4 -1 -9 -1 -5 -2 -1 -6 -1 -0 -9 -6 -6 -0 -2 -1 -7 -9 -5 -8 -8 -7 -8 -3 -0 -2 -1 -9 -9 -9 -1 -3 -3 -6 -9 -0 -3 -7 -4 -1 -5 -1 -7 -5 -4 -2 -5 -0 -6 -4 -1 -9 -7 -9 -6 -7 -8 -0 -2 -3 -9 -8 -7 -2 -3 -4 -9 -5 -6 -8 -6 -6 -1 -2 -8 -1 -7 -6 -9 -1 -8 -7 -6 -2 -2 -7 -3 -0 -4 -6 -8 -0 -1 -7 -3 -2 -0 -8 -8 -3 -5 -4 -1 -8 -6 -4 -1 -0 -1 -1 -0 -2 -4 -7 -6 -4 -3 -8 -6 -4 -6 -9 -1 -4 -6 -1 -6 -9 -3 -7 -4 -9 -1 -3 -8 -2 -9 -4 -9 -5 -8 -8 -9 -2 -6 -1 -5 -5 -3 -6 -7 -0 -3 -4 -2 -6 -7 -6 -1 -5 -7 -7 -2 -7 -3 -3 -3 -9 -1 -2 -1 -1 -1 -1 -6 -0 -6 -9 -6 -9 -6 -6 -1 -1 -0 -0 -7 -6 -9 -5 -1 -7 -6 -9 -7 -4 -8 -2 -3 -5 -8 -6 -2 -2 -1 -0 -8 -9 -2 -4 -4 -0 -0 -9 -6 -8 -0 -3 -9 -7 -9 -7 -9 -7 -3 -7 -2 -8 -2 -3 -8 -6 -1 -2 -7 -2 -1 -2 -7 -1 -4 -0 -5 -3 -5 -5 -3 -3 -8 -6 -9 -9 -0 -2 -5 -7 -9 -6 -8 -6 -2 -3 -1 -7 -3 -8 -4 -9 -9 -0 -3 -8 -7 -4 -8 -2 -8 -7 -7 -5 -7 -8 -6 -9 -5 -1 -5 -9 -9 -0 -4 -9 -7 -4 -7 -9 -0 -1 -4 -3 -5 -9 -0 -9 -4 -4 -8 -6 -1 -2 -1 -1 -9 -2 -7 -7 -0 -1 -5 -1 -6 -9 -8 -3 -4 -0 -3 -1 -0 -5 -3 -9 -8 -1 -7 -8 -3 -6 -8 -1 -1 -7 -1 -4 -5 -0 -8 -9 -6 -0 -2 -7 -1 -6 -1 -0 -1 -2 -1 -0 -5 -4 -5 -1 -2 -1 -1 -2 -7 -3 -3 -6 -0 -2 -8 -5 -9 -8 -9 -3 -5 -3 -4 -0 -6 -6 -3 -5 -4 -6 -9 -1 -2 -3 -9 -0 -3 -4 -9 -6 -8 -6 -9 -3 -8 -4 -8 -4 -1 -1 -7 -3 -8 -1 -2 -3 -1 -9 -4 -7 -2 -4 -0 -1 -4 -3 -6 -2 -4 -1 -5 -9 -7 -1 -7 -6 -6 -1 -6 -7 -4 -8 -2 -1 -0 -9 -6 -2 -5 -5 -3 -9 -0 -6 -2 -5 -6 -0 -3 -4 -3 -6 -7 -6 -0 -3 -5 -5 -8 -4 -0 -6 -9 -5 -6 -0 -1 -7 -0 -7 -5 -6 -4 -3 -4 -4 -6 -2 -2 -4 -7 -7 -0 -7 -8 -7 -4 -9 -2 -4 -7 -1 -3 -9 -4 -0 -1 -2 -9 -7 -9 -9 -3 -4 -5 -5 -1 -4 -5 -6 -1 -2 -8 -8 -4 -6 -5 -9 -6 -1 -0 -5 -4 -0 -3 -1 -1 -5 -5 -3 -1 -2 -4 -6 -9 -9 -4 -1 -7 -9 -0 -4 -1 -1 -9 -3 -6 -2 -2 -1 -6 -7 -7 -1 -7 -3 -0 -1 -1 -1 -3 -1 -1 -5 -2 -7 -1 -2 -1 -8 -8 -0 -7 -5 -5 -4 -0 -8 -7 -7 -2 -4 -5 -8 -2 -0 -7 -4 -1 -1 -1 -1 -5 -4 -2 -1 -0 -2 -4 -7 -0 -2 -8 -0 -2 -1 -9 -7 -3 -3 -4 -4 -1 -1 -4 -2 -3 -1 -0 -9 -8 -5 -9 -8 -6 -1 -3 -1 -6 -3 -7 -6 -1 -7 -3 -3 -5 -7 -7 -6 -0 -8 -1 -7 -9 -7 -3 -2 -1 -3 -9 -4 -5 -1 -9 -7 -7 -2 -3 -4 -8 -0 -9 -4 -1 -1 -7 -2 -6 -6 -4 -1 -0 -9 -2 -1 -3 -7 -9 -0 -2 -8 -5 -8 -9 -9 -7 -5 -6 -8 -7 -4 -7 -0 -1 -7 -3 -5 -6 -9 -9 -5 -3 -1 -2 -0 -8 -1 -4 -1 -1 -1 -8 -9 -9 -7 -9 -6 -9 -6 -2 -4 -4 -2 -1 -8 -7 -5 -4 -6 -2 -1 -6 -7 -1 -9 -0 -0 -5 -8 -9 -7 -2 -0 -5 -9 -2 -2 -4 -2 -4 -3 -0 -1 -8 -5 -1 -8 -2 -1 -3 -2 -4 -0 -4 -1 -8 -3 -7 -9 -5 -8 -8 -6 -4 -5 -7 -4 -9 -6 -8 -8 -6 -6 -5 -7 -9 -9 -4 -2 -3 -6 -6 -0 -0 -6 -6 -9 -1 -4 -4 -7 -3 -7 -3 -2 -7 -8 -4 -5 -6 -2 -0 -3 -9 -5 -0 -0 -7 -8 -8 -3 -5 -8 -6 -3 -7 -5 -0 -2 -7 -8 -6 -1 -5 -3 -4 -4 -3 -4 -1 -3 -3 -8 -2 -1 -5 -7 -1 -7 -4 -9 -3 -1 -7 -8 -3 -6 -8 -9 -5 -7 -2 -8 -8 -8 -7 -2 -9 -7 -8 -1 -7 -8 -2 -0 -5 -1 -0 -6 -9 -6 -4 -9 -6 -9 -8 -3 -1 -6 -9 -9 -4 -9 -6 -8 -5 -8 -1 -9 -3 -9 -3 -1 -8 -0 -5 -2 -7 -1 -0 -5 -2 -4 -9 -3 -8 -9 -6 -6 -2 -8 -6 -7 -0 -0 -3 -3 -6 -5 -1 -1 -0 -9 -3 -1 -5 -8 -3 -2 -6 -8 -3 -8 -7 -4 -2 -9 -7 -3 -9 -8 -2 -3 -5 -1 -0 -9 -9 -2 -3 -7 -7 -9 -7 -8 -6 -0 -5 -4 -3 -7 -4 -1 -3 -4 -8 -7 -0 -0 -5 -6 -4 -5 -1 -9 -9 -2 -7 -7 -9 -2 -9 -8 -2 -1 -8 -2 -3 -5 -5 -3 -2 -0 -9 -8 -6 -1 -2 -0 -1 -1 -5 -6 -8 -8 -1 -3 -9 -0 -0 -3 -2 -4 -8 -9 -8 -4 -1 -9 -0 -9 -9 -2 -9 -4 -4 -7 -9 -9 -1 -2 -0 -5 -3 -9 -6 -7 -2 -5 -4 -4 -0 -1 -0 -9 -4 -0 -1 -9 -6 -0 -6 -1 -9 -3 -7 -8 -2 -7 -9 -2 -8 -7 -5 -6 -4 -9 -8 -7 -0 -1 -1 -6 -9 -6 -3 -2 -6 -8 -5 -5 -5 -2 -8 -3 -6 -2 -6 -9 -6 -5 -2 -0 -5 -8 -7 -4 -9 -7 -0 -2 -1 -9 -0 -8 -1 -0 -6 -2 -5 -0 -9 -0 -8 -5 -4 -6 -5 -3 -8 -7 -0 -9 -1 -4 -1 -5 -2 -2 -4 -2 -9 -8 -7 -1 -8 -3 -4 -7 -1 -9 -0 -9 -8 -7 -9 -4 -1 -9 -7 -0 -0 -5 -7 -4 -0 -6 -5 -4 -2 -5 -5 -5 -7 -1 -5 -3 -1 -8 -0 -9 -4 -0 -1 -6 -8 -0 -6 -2 -3 -4 -4 -2 -5 -6 -2 -1 -6 -1 -5 -9 -1 -7 -9 -0 -7 -9 -4 -2 -6 -0 -6 -6 -1 -7 -2 -8 -0 -6 -0 -1 -9 -9 -3 -7 -0 -2 -4 -6 -2 -1 -2 -1 -7 -6 -9 -0 -0 -1 -4 -8 -7 -3 -8 -6 -9 -3 -1 -3 -7 -9 -6 -0 -1 -7 -1 -1 -4 -1 -6 -6 -3 -1 -8 -1 -9 -6 -2 -1 -0 -1 -6 -7 -9 -0 -5 -1 -3 -6 -6 -1 -4 -9 -4 -5 -5 -2 -6 -6 -3 -4 -3 -4 -7 -0 -7 -0 -8 -2 -0 -0 -7 -7 -1 -0 -5 -2 -2 -3 -9 -1 -7 -6 -8 -3 -2 -0 -1 -5 -8 -2 -6 -0 -0 -5 -9 -0 -5 -6 -6 -4 -2 -7 -1 -2 -9 -5 -8 -7 -4 -9 -2 -8 -9 -8 -3 -3 -7 -3 -2 -0 -4 -9 -0 -3 -7 -6 -2 -0 -0 -7 -2 -1 -7 -1 -0 -8 -6 -0 -5 -7 -9 -8 -1 -5 -1 -9 -6 -3 -2 -0 -6 -8 -7 -0 -3 -9 -9 -0 -9 -5 -7 -6 -2 -2 -5 -3 -8 -5 -2 -1 -1 -5 -4 -6 -0 -2 -1 -2 -0 -7 -1 -1 -1 -7 -9 -0 -5 -9 -0 -8 -1 -7 -4 -2 -7 -1 -9 -3 -3 -7 -9 -4 -2 -7 -3 -7 -2 -5 -9 -0 -2 -6 -8 -7 -8 -8 -7 -0 -2 -9 -4 -0 -1 -7 -6 -7 -2 -3 -7 -6 -9 -9 -0 -3 -6 -4 -4 -2 -3 -1 -7 -6 -3 -0 -7 -0 -2 -7 -7 -7 -0 -0 -1 -9 -0 -6 -9 -7 -8 -1 -5 -1 -1 -2 -3 -9 -0 -0 -5 -2 -2 -3 -0 -9 -9 -9 -8 -2 -5 -1 -1 -5 -2 -8 -1 -5 -1 -8 -5 -3 -6 -7 -9 -1 -8 -8 -2 -1 -8 -8 -0 -9 -0 -2 -3 -5 -6 -0 -0 -0 -8 -0 -6 -3 -3 -7 -2 -5 -6 -8 -7 -5 -8 -0 -2 -7 -4 -0 -1 -3 -1 -0 -0 -0 -9 -5 -3 -0 -3 -7 -0 -6 -8 -9 -2 -6 -7 -7 -3 -1 -8 -7 -6 -3 -2 -6 -4 -9 -5 -8 -2 -7 -3 -2 -4 -8 -4 -9 -4 -1 -1 -6 -8 -9 -5 -1 -7 -3 -5 -0 -1 -3 -4 -5 -6 -2 -1 -9 -4 -9 -6 -7 -0 -1 -6 -8 -4 -3 -5 -4 -1 -6 -4 -5 -1 -2 -6 -9 -2 -4 -7 -0 -2 -1 -8 -1 -7 -7 -5 -3 -2 -8 -7 -5 -1 -4 -9 -4 -1 -7 -9 -7 -0 -6 -0 -2 -8 -2 -9 -4 -3 -0 -3 -8 -9 -1 -3 -5 -9 -2 -9 -1 -8 -1 -6 -0 -4 -8 -0 -9 -1 -0 -5 -9 -7 -7 -5 -8 -4 -7 -9 -7 -9 -6 -9 -5 -8 -4 -0 -0 -1 -9 -6 -6 -1 -6 -0 -2 -1 -8 -5 -7 -9 -4 -1 -4 -6 -2 -8 -0 -6 -5 -6 -1 -1 -3 -1 -7 -0 -3 -3 -5 -8 -7 -2 -3 -3 -7 -3 -9 -9 -8 -6 -6 -0 -5 -5 -9 -3 -0 -6 -1 -1 -3 -2 -6 -1 -5 -3 -2 -3 -8 -0 -0 -0 -1 -5 -2 -8 -7 -1 -0 -4 -9 -2 -3 -9 -7 -4 -4 -9 -6 -9 -9 -3 -9 -8 -1 -0 -6 -9 -1 -9 -4 -0 -9 -5 -0 -8 -9 -9 -4 -3 -1 -5 -5 -0 -6 -6 -6 -5 -6 -4 -4 -0 -4 -8 -5 -9 -4 -6 -4 -5 -8 -5 -7 -4 -1 -1 -6 -8 -3 -1 -0 -3 -5 -3 -7 -7 -1 -9 -9 -7 -3 -5 -9 -6 -2 -5 -2 -2 -8 -6 -5 -0 -7 -7 -3 -9 -8 -5 -0 -8 -9 -0 -6 -3 -3 -5 -9 -2 -6 -1 -3 -1 -8 -8 -1 -2 -0 -3 -5 -0 -1 -8 -0 -3 -3 -9 -8 -4 -1 -1 -3 -5 -1 -7 -4 -1 -5 -9 -9 -0 -7 -7 -6 -4 -1 -6 -1 -7 -8 -2 -1 -9 -4 -0 -9 -9 -3 -4 -2 -4 -7 -3 -9 -7 -1 -6 -5 -7 -8 -0 -1 -9 -6 -2 -6 -1 -0 -2 -4 -9 -6 -1 -1 -2 -8 -2 -6 -4 -7 -7 -1 -6 -9 -2 -9 -2 -7 -8 -6 -6 -4 -6 -5 -5 -2 -5 -7 -6 -7 -7 -9 -3 -0 -8 -9 -4 -5 -3 -8 -1 -3 -0 -9 -5 -1 -2 -0 -6 -3 -5 -9 -1 -5 -9 -9 -8 -0 -4 -5 -6 -6 -0 -6 -5 -1 -2 -6 -0 -2 -2 -9 -8 -1 -6 -2 -1 -9 -4 -8 -4 -1 -9 -9 -7 -1 -6 -7 -9 -9 -2 -4 -4 -7 -5 -9 -8 -6 -3 -6 -7 -2 -4 -6 -1 -4 -1 -9 -1 -6 -5 -6 -8 -5 -5 -9 -6 -0 -6 -9 -2 -5 -7 -6 -5 -2 -7 -7 -3 -5 -6 -6 -5 -9 -9 -5 -4 -0 -5 -5 -1 -8 -1 -2 -1 -1 -2 -3 -6 -8 -2 -1 -2 -5 -9 -2 -1 -2 -8 -6 -8 -8 -6 -0 -0 -7 -6 -2 -4 -5 -2 -9 -7 -5 -4 -6 -8 -1 -8 -5 -9 -1 -9 -3 -0 -9 -8 -8 -0 -5 -7 -3 -1 -8 -9 -3 -7 -0 -5 -7 -1 -1 -8 -8 -0 -4 -9 -6 -1 -8 -9 -6 -6 -7 -2 -9 -0 -8 -3 -3 -1 -9 -7 -6 -1 -3 -0 -2 -8 -2 -6 -5 -9 -7 -1 -7 -1 -5 -5 -1 -6 -1 -7 -2 -9 -9 -8 -1 -9 -5 -1 -4 -5 -2 -5 -1 -9 -0 -7 -1 -7 -3 -0 -6 -0 -6 -8 -5 -6 -1 -1 -1 -0 -7 -3 -3 -7 -4 -6 -7 -3 -1 -6 -1 -8 -9 -7 -6 -9 -1 -1 -4 -9 -1 -4 -1 -8 -2 -3 -6 -7 -1 -3 -4 -1 -0 -0 -8 -9 -6 -3 -0 -5 -5 -9 -0 -6 -4 -6 -0 -2 -0 -9 -1 -9 -7 -3 -2 -9 -3 -7 -4 -3 -8 -7 -5 -7 -8 -6 -0 -1 -6 -3 -9 -5 -0 -6 -7 -3 -1 -5 -5 -9 -8 -8 -1 -5 -1 -3 -7 -1 -2 -9 -5 -4 -6 -7 -3 -2 -0 -9 -5 -0 -2 -9 -0 -1 -1 -0 -5 -5 -3 -6 -9 -6 -1 -1 -7 -3 -0 -6 -7 -5 -0 -1 -1 -1 -5 -4 -5 -2 -4 -2 -8 -9 -1 -3 -5 -1 -7 -6 -5 -1 -1 -9 -4 -0 -7 -8 -5 -9 -2 -9 -2 -1 -5 -1 -0 -4 -3 -9 -8 -7 -0 -4 -9 -8 -2 -7 -7 -0 -1 -7 -4 -5 -7 -0 -3 -9 -0 -6 -4 -3 -7 -3 -7 -4 -9 -9 -7 -9 -1 -3 -6 -5 -8 -1 -0 -8 -9 -0 -1 -0 -8 -7 -5 -4 -4 -1 -2 -2 -7 -1 -2 -0 -2 -0 -6 -8 -7 -1 -3 -3 -1 -3 -8 -0 -5 -8 -1 -1 -9 -9 -1 -1 -3 -2 -2 -3 -4 -0 -1 -5 -6 -3 -3 -3 -9 -7 -1 -0 -5 -8 -7 -3 -9 -1 -9 -2 -5 -8 -9 -6 -5 -7 -2 -6 -2 -9 -2 -2 -0 -2 -0 -5 -1 -9 -8 -1 -5 -7 -1 -8 -4 -1 -9 -3 -1 -1 -8 -6 -4 -2 -0 -1 -0 -7 -2 -7 -8 -3 -1 -7 -1 -2 -4 -3 -1 -6 -5 -0 -7 -9 -1 -5 -9 -7 -5 -3 -9 -7 -2 -2 -9 -6 -1 -1 -3 -9 -0 -0 -9 -6 -0 -6 -4 -2 -9 -5 -3 -6 -6 -1 -1 -2 -6 -1 -6 -7 -2 -0 -1 -8 -9 -1 -7 -8 -7 -2 -7 -0 -0 -1 -5 -5 -8 -9 -4 -5 -4 -9 -9 -2 -0 -3 -1 -7 -1 -1 -4 -7 -2 -4 -3 -3 -5 -3 -8 -0 -8 -9 -6 -1 -9 -0 -8 -6 -6 -5 -9 -0 -2 -2 -9 -9 -8 -5 -7 -1 -8 -5 -1 -0 -4 -2 -4 -7 -3 -1 -9 -5 -0 -9 -9 -1 -2 -4 -1 -6 -9 -6 -3 -6 -4 -5 -9 -9 -0 -7 -7 -6 -6 -6 -0 -7 -4 -5 -6 -3 -9 -0 -0 -4 -2 -1 -5 -3 -0 -1 -6 -6 -7 -1 -2 -0 -9 -2 -4 -1 -5 -4 -9 -1 -6 -1 -7 -2 -1 -5 -0 -7 -1 -3 -2 -1 -1 -8 -4 -9 -5 -4 -0 -4 -6 -2 -0 -1 -6 -9 -6 -5 -8 -2 -5 -2 -1 -7 -5 -0 -0 -8 -8 -0 -0 -7 -3 -1 -3 -9 -5 -1 -3 -7 -8 -9 -0 -8 -2 -8 -0 -7 -1 -7 -6 -3 -0 -6 -4 -3 -9 -6 -7 -4 -2 -0 -9 -2 -2 -6 -1 -1 -6 -4 -5 -2 -3 -6 -9 -9 -5 -5 -2 -4 -2 -1 -5 -3 -8 -6 -9 -2 -1 -1 -4 -6 -5 -1 -1 -7 -3 -8 -3 -8 -1 -1 -9 -8 -1 -6 -0 -4 -2 -2 -8 -5 -3 -4 -3 -2 -7 -0 -3 -9 -5 -4 -7 -4 -8 -0 -6 -9 -3 -1 -5 -4 -5 -0 -1 -7 -0 -4 -5 -3 -8 -0 -6 -1 -3 -6 -9 -6 -5 -9 -7 -1 -5 -6 -5 -2 -5 -0 -6 -2 -1 -9 -9 -1 -6 -3 -3 -3 -7 -2 -9 -8 -5 -0 -1 -6 -6 -0 -1 -1 -8 -7 -5 -4 -9 -7 -0 -8 -8 -6 -7 -1 -4 -3 -6 -8 -8 -1 -1 -6 -9 -8 -1 -1 -1 -6 -1 -6 -9 -3 -5 -0 -5 -7 -7 -5 -7 -5 -5 -6 -0 -0 -1 -3 -4 -1 -8 -8 -7 -7 -2 -8 -6 -4 -6 -4 -8 -0 -6 -6 -1 -5 -1 -0 -6 -1 -6 -7 -1 -3 -2 -4 -0 -7 -9 -3 -4 -4 -3 -2 -5 -0 -9 -5 -5 -6 -8 -5 -6 -4 -9 -8 -6 -0 -9 -9 -1 -7 -3 -1 -7 -9 -9 -9 -2 -8 -0 -5 -1 -9 -3 -2 -4 -3 -1 -5 -8 -1 -4 -4 -1 -9 -7 -5 -6 -3 -6 -0 -3 -9 -1 -9 -4 -5 -1 -3 -9 -9 -4 -3 -2 -8 -1 -8 -1 -4 -1 -9 -0 -4 -0 -9 -0 -4 -1 -5 -0 -8 -0 -9 -0 -8 -1 -8 -7 -1 -8 -1 -6 -4 -0 -9 -6 -0 -7 -9 -2 -2 -5 -1 -4 -3 -3 -6 -9 -1 -0 -7 -2 -5 -4 -7 -8 -1 -9 -9 -3 -4 -3 -3 -8 -1 -7 -0 -8 -5 -7 -2 -1 -8 -6 -1 -7 -7 -9 -1 -0 -6 -5 -0 -2 -3 -9 -1 -7 -0 -8 -6 -1 -4 -9 -5 -7 -2 -4 -2 -3 -8 -2 -1 -7 -5 -1 -4 -5 -1 -8 -1 -7 -4 -4 -1 -3 -1 -0 -5 -3 -9 -7 -6 -9 -1 -1 -5 -1 -8 -4 -2 -5 -5 -8 -7 -2 -4 -0 -7 -9 -8 -6 -3 -8 -7 -4 -6 -2 -6 -4 -2 -2 -8 -8 -3 -1 -9 -1 -4 -0 -2 -1 -0 -0 -0 -9 -2 -3 -8 -3 -1 -7 -3 -0 -2 -0 -6 -0 -2 -7 -4 -5 -6 -2 -8 -9 -3 -0 -0 -0 -7 -9 -1 -6 -8 -1 -4 -2 -1 -2 -0 -6 -7 -4 -3 -5 -2 -0 -0 -4 -4 -9 -8 -5 -1 -9 -1 -2 -1 -5 -4 -9 -9 -6 -1 -8 -1 -5 -9 -9 -5 -6 -7 -6 -3 -8 -3 -4 -2 -3 -6 -3 -6 -5 -3 -4 -2 -6 -0 -1 -9 -1 -7 -7 -2 -7 -2 -9 -1 -0 -4 -6 -2 -5 -6 -0 -3 -1 -4 -8 -2 -1 -5 -5 -7 -4 -3 -0 -3 -7 -0 -2 -8 -6 -1 -1 -4 -0 -9 -0 -4 -1 -5 -3 -9 -4 -6 -5 -0 -5 -0 -1 -4 -8 -1 -0 -5 -8 -9 -6 -5 -4 -5 -5 -8 -3 -1 -9 -9 -2 -0 -3 -7 -3 -4 -3 -0 -6 -6 -5 -9 -3 -9 -2 -5 -9 -6 -3 -6 -9 -8 -2 -6 -3 -4 -1 -1 -3 -5 -8 -0 -4 -5 -4 -0 -2 -0 -6 -9 -1 -2 -3 -1 -1 -0 -1 -4 -4 -0 -6 -7 -1 -7 -2 -3 -6 -4 -3 -1 -8 -3 -9 -0 -2 -9 -9 -1 -3 -8 -6 -3 -7 -8 -0 -2 -9 -9 -9 -1 -0 -1 -5 -5 -4 -2 -4 -5 -3 -8 -6 -7 -9 -5 -2 -5 -1 -1 -2 -5 -0 -6 -9 -8 -8 -7 -1 -9 -9 -9 -2 -1 -3 -9 -6 -3 -4 -6 -1 -0 -4 -9 -1 -5 -3 -7 -9 -7 -6 -7 -6 -5 -9 -9 -6 -6 -9 -0 -4 -7 -7 -8 -9 -3 -0 -3 -2 -2 -9 -3 -0 -7 -9 -6 -1 -0 -8 -3 -3 -5 -2 -1 -2 -2 -2 -9 -1 -8 -3 -3 -5 -7 -6 -2 -2 -0 -1 -7 -5 -3 -7 -0 -1 -1 -9 -9 -9 -1 -1 -4 -3 -7 -2 -7 -3 -4 -7 -1 -0 -5 -6 -9 -7 -7 -0 -3 -9 -5 -4 -4 -5 -9 -9 -9 -4 -5 -2 -7 -3 -0 -3 -3 -8 -1 -4 -8 -1 -2 -0 -1 -6 -9 -0 -7 -7 -3 -6 -1 -0 -6 -5 -9 -3 -4 -7 -5 -6 -4 -2 -2 -2 -5 -3 -7 -8 -0 -8 -6 -1 -6 -4 -4 -0 -9 -0 -3 -5 -1 -7 -1 -4 -1 -8 -4 -9 -8 -0 -3 -5 -7 -4 -4 -6 -6 -8 -6 -9 -3 -1 -1 -6 -1 -9 -9 -3 -7 -7 -2 -7 -2 -2 -0 -6 -7 -0 -1 -5 -6 -2 -6 -2 -5 -5 -7 -6 -9 -7 -9 -4 -1 -3 -2 -6 -1 -5 -9 -9 -7 -8 -7 -0 -1 -4 -5 -7 -6 -5 -6 -0 -4 -7 -5 -1 -6 -1 -1 -9 -9 -8 -3 -5 -1 -7 -4 -4 -2 -9 -9 -7 -1 -7 -5 -2 -6 -2 -1 -4 -1 -5 -3 -9 -7 -9 -4 -3 -2 -6 -9 -1 -3 -5 -7 -0 -3 -9 -3 -5 -9 -1 -6 -8 -7 -2 -0 -0 -5 -2 -1 -8 -4 -4 -4 -4 -2 -4 -5 -9 -3 -9 -6 -7 -4 -0 -3 -4 -8 -7 -6 -1 -3 -2 -1 -0 -3 -0 -3 -5 -1 -4 -2 -8 -8 -0 -2 -8 -3 -9 -5 -9 -7 -8 -2 -6 -1 -2 -4 -1 -3 -4 -3 -2 -0 -1 -8 -4 -6 -8 -8 -7 -8 -5 -1 -2 -2 -0 -7 -6 -9 -1 -8 -7 -6 -2 -4 -6 -0 -2 -3 -5 -0 -5 -7 -4 -1 -7 -8 -9 -9 -1 -5 -0 -2 -0 -3 -3 -6 -4 -9 -4 -8 -6 -5 -2 -9 -0 -2 -1 -9 -8 -2 -5 -4 -7 -4 -8 -3 -4 -5 -2 -6 -4 -1 -3 -0 -2 -1 -2 -7 -2 -2 -6 -6 -0 -1 -4 -6 -1 -0 -2 -9 -8 -6 -1 -1 -9 -5 -6 -7 -6 -7 -5 -0 -3 -9 -9 -2 -6 -6 -9 -5 -9 -3 -2 -7 -4 -1 -4 -8 -7 -8 -4 -1 -8 -5 -6 -0 -8 -9 -3 -2 -6 -4 -6 -6 -5 -1 -8 -6 -8 -3 -7 -1 -1 -3 -6 -9 -4 -6 -0 -3 -9 -2 -6 -3 -7 -4 -3 -4 -1 -7 -2 -5 -6 -9 -6 -6 -3 -9 -4 -1 -8 -2 -3 -6 -0 -7 -7 -7 -3 -1 -0 -1 -0 -6 -0 -6 -7 -5 -5 -1 -9 -2 -5 -3 -3 -3 -7 -1 -0 -9 -2 -3 -2 -9 -3 -1 -8 -0 -1 -3 -8 -5 -0 -1 -9 -8 -1 -0 -1 -2 -6 -8 -2 -7 -4 -7 -7 -0 -1 -9 -9 -6 -1 -6 -7 -1 -3 -5 -3 -9 -0 -8 -2 -9 -4 -9 -2 -6 -1 -7 -9 -9 -0 -9 -7 -1 -9 -2 -7 -4 -6 -3 -3 -9 -7 -8 -1 -1 -0 -7 -9 -2 -5 -5 -5 -6 -5 -0 -9 -5 -5 -0 -0 -1 -7 -0 -1 -6 -9 -6 -2 -6 -9 -0 -0 -5 -3 -4 -6 -4 -2 -0 -7 -1 -2 -6 -2 -2 -6 -7 -5 -0 -2 -8 -4 -0 -9 -2 -6 -5 -9 -7 -8 -9 -5 -3 -9 -1 -1 -2 -5 -9 -4 -2 -5 -0 -1 -4 -0 -9 -6 -6 -0 -7 -8 -9 -7 -5 -3 -8 -9 -9 -1 -1 -6 -3 -3 -5 -0 -1 -1 -7 -8 -5 -7 -6 -5 -5 -9 -9 -0 -9 -1 -1 -6 -0 -4 -8 -2 -6 -7 -9 -5 -9 -6 -9 -7 -1 -8 -8 -4 -7 -2 -3 -7 -9 -0 -0 -1 -9 -5 -2 -8 -9 -1 -4 -5 -7 -8 -5 -5 -6 -0 -6 -8 -9 -2 -2 -0 -8 -8 -7 -7 -5 -7 -2 -7 -1 -4 -6 -8 -4 -9 -5 -1 -1 -7 -6 -9 -8 -1 -6 -6 -4 -3 -3 -0 -5 -0 -3 -1 -6 -2 -6 -1 -6 -7 -6 -0 -6 -4 -8 -4 -6 -7 -4 -8 -8 -7 -4 -3 -1 -0 -9 -4 -0 -1 -8 -9 -6 -0 -6 -9 -9 -1 -9 -4 -2 -0 -9 -9 -1 -2 -9 -6 -5 -8 -1 -7 -5 -7 -2 -5 -8 -0 -0 -6 -5 -9 -3 -5 -4 -0 -3 -8 -3 -6 -9 -0 -0 -5 -8 -9 -6 -7 -2 -2 -8 -9 -6 -1 -6 -4 -4 -6 -6 -4 -0 -0 -9 -6 -4 -9 -9 -3 -0 -3 -1 -2 -1 -5 -1 -9 -4 -5 -3 -1 -9 -8 -2 -0 -2 -9 -2 -3 -3 -7 -6 -9 -6 -1 -3 -0 -1 -3 -7 -7 -9 -6 -9 -4 -5 -5 -6 -8 -3 -8 -3 -5 -7 -6 -3 -7 -7 -5 -4 -5 -1 -2 -8 -8 -7 -1 -5 -6 -5 -2 -5 -5 -1 -5 -6 -1 -4 -3 -0 -0 -3 -4 -2 -9 -0 -5 -2 -9 -3 -0 -6 -3 -2 -9 -6 -1 -8 -5 -7 -0 -5 -4 -1 -8 -8 -2 -9 -2 -0 -1 -4 -9 -7 -6 -3 -8 -4 -5 -0 -6 -6 -0 -5 -9 -0 -7 -4 -8 -9 -5 -9 -7 -9 -0 -1 -1 -1 -2 -0 -7 -5 -0 -6 -0 -8 -7 -1 -9 -8 -5 -2 -6 -1 -6 -9 -2 -3 -9 -8 -8 -9 -0 -2 -9 -4 -8 -5 -1 -0 -9 -0 -1 -7 -9 -4 -0 -1 -3 -9 -8 -9 -4 -5 -0 -1 -5 -8 -8 -1 -6 -9 -7 -0 -1 -7 -5 -6 -4 -6 -1 -9 -9 -9 -3 -9 -6 -9 -0 -0 -1 -5 -9 -3 -3 -2 -1 -1 -2 -4 -3 -1 -8 -5 -2 -3 -3 -5 -4 -8 -0 -5 -3 -5 -9 -3 -5 -8 -5 -1 -6 -0 -8 -9 -8 -0 -4 -1 -0 -1 -3 -1 -8 -6 -3 -1 -1 -0 -5 -8 -6 -9 -5 -1 -6 -1 -1 -6 -4 -3 -8 -6 -9 -4 -2 -8 -6 -7 -2 -7 -7 -6 -8 -2 -2 -0 -7 -0 -7 -5 -0 -9 -9 -6 -4 -5 -6 -1 -2 -0 -3 -9 -7 -6 -0 -3 -4 -1 -7 -7 -7 -1 -0 -0 -6 -0 -6 -5 -9 -7 -8 -2 -5 -1 -1 -9 -3 -8 -8 -9 -1 -2 -6 -6 -6 -9 -0 -3 -8 -6 -1 -5 -6 -6 -4 -3 -4 -9 -0 -0 -1 -0 -9 -2 -2 -1 -7 -5 -4 -1 -6 -0 -3 -8 -9 -9 -7 -8 -2 -7 -8 -5 -0 -2 -1 -8 -9 -1 -6 -9 -3 -9 -9 -1 -8 -7 -9 -1 -2 -2 -5 -6 -5 -8 -7 -3 -6 -1 -2 -6 -8 -1 -8 -6 -7 -4 -1 -1 -3 -4 -0 -9 -1 -1 -0 -1 -8 -1 -3 -9 -0 -3 -8 -5 -9 -0 -9 -8 -7 -7 -1 -0 -1 -0 -3 -4 -9 -6 -3 -0 -2 -4 -9 -7 -1 -9 -1 -9 -3 -8 -2 -0 -4 -7 -3 -2 -6 -7 -1 -5 -1 -1 -2 -4 -0 -0 -4 -8 -8 -5 -2 -5 -8 -5 -9 -0 -3 -2 -4 -8 -2 -0 -2 -7 -5 -1 -6 -8 -9 -1 -0 -7 -2 -6 -1 -1 -6 -0 -2 -9 -6 -0 -0 -8 -7 -4 -3 -6 -8 -1 -6 -7 -4 -6 -9 -3 -2 -0 -9 -8 -6 -6 -3 -0 -2 -0 -3 -0 -7 -2 -2 -1 -8 -4 -7 -9 -6 -7 -3 -1 -3 -7 -0 -3 -7 -2 -2 -2 -0 -7 -9 -1 -2 -0 -6 -6 -2 -3 -6 -7 -4 -9 -4 -5 -8 -9 -3 -7 -4 -2 -9 -9 -8 -6 -7 -0 -3 -0 -9 -1 -3 -1 -6 -5 -0 -6 -0 -1 -9 -6 -9 -0 -8 -8 -7 -4 -0 -9 -9 -6 -8 -0 -2 -4 -8 -4 -4 -1 -7 -1 -1 -9 -2 -2 -7 -6 -8 -0 -2 -0 -6 -0 -1 -9 -0 -3 -9 -9 -7 -9 -5 -0 -3 -8 -9 -8 -0 -1 -4 -6 -7 -9 -2 -7 -9 -7 -6 -5 -8 -2 -1 -4 -9 -7 -5 -8 -1 -2 -1 -1 -7 -1 -9 -6 -0 -1 -9 -9 -6 -0 -1 -8 -1 -0 -7 -4 -6 -6 -2 -9 -2 -1 -3 -5 -1 -9 -3 -1 -9 -3 -4 -1 -1 -8 -9 -9 -7 -5 -4 -1 -6 -0 -1 -2 -6 -0 -3 -0 -6 -8 -7 -2 -0 -3 -9 -7 -8 -4 -6 -4 -0 -5 -8 -9 -3 -3 -0 -1 -2 -1 -3 -8 -7 -2 -8 -2 -8 -0 -4 -6 -4 -2 -1 -6 -1 -4 -4 -1 -1 -6 -5 -7 -1 -1 -6 -1 -5 -9 -4 -3 -3 -3 -9 -0 -7 -4 -1 -3 -3 -1 -1 -6 -5 -7 -3 -9 -5 -4 -5 -6 -4 -1 -5 -9 -3 -9 -3 -8 -0 -8 -9 -6 -8 -5 -7 -9 -0 -9 -7 -2 -9 -1 -3 -5 -1 -4 -7 -3 -8 -1 -5 -7 -5 -0 -2 -7 -3 -9 -0 -1 -3 -2 -2 -2 -4 -0 -0 -4 -9 -5 -9 -1 -7 -0 -1 -4 -0 -8 -3 -0 -4 -0 -9 -6 -9 -0 -1 -0 -7 -3 -5 -6 -8 -2 -9 -1 -6 -1 -5 -1 -9 -1 -9 -5 -8 -9 -9 -6 -3 -8 -7 -5 -0 -3 -9 -3 -7 -1 -8 -7 -9 -3 -3 -9 -7 -0 -6 -3 -9 -4 -7 -6 -4 -3 -5 -5 -9 -7 -4 -4 -1 -5 -1 -0 -3 -9 -9 -1 -6 -5 -6 -4 -3 -3 -3 -3 -7 -9 -7 -5 -1 -2 -2 -0 -9 -9 -1 -4 -5 -1 -9 -4 -2 -1 -2 -8 -0 -0 -2 -8 -3 -2 -8 -8 -3 -4 -4 -1 -8 -1 -2 -0 -6 -4 -6 -9 -6 -1 -9 -0 -3 -5 -5 -5 -2 -8 -5 -8 -1 -2 -8 -9 -4 -4 -0 -9 -8 -0 -3 -4 -2 -7 -7 -0 -7 -6 -8 -9 -9 -0 -0 -9 -2 -3 -1 -9 -2 -9 -2 -0 -6 -9 -3 -7 -9 -7 -5 -2 -5 -8 -7 -1 -1 -2 -1 -4 -7 -4 -8 -7 -4 -0 -4 -0 -5 -0 -0 -2 -6 -1 -0 -8 -5 -5 -6 -2 -2 -1 -3 -5 -8 -3 -3 -6 -7 -3 -6 -4 -5 -9 -6 -2 -7 -9 -8 -2 -7 -3 -9 -7 -8 -1 -9 -8 -3 -6 -9 -2 -2 -6 -2 -8 -0 -7 -7 -8 -9 -6 -6 -9 -3 -6 -8 -0 -4 -3 -8 -2 -5 -0 -6 -1 -1 -9 -2 -7 -1 -5 -7 -3 -9 -1 -1 -3 -3 -7 -9 -2 -1 -3 -3 -8 -3 -9 -4 -2 -1 -4 -6 -7 -6 -6 -2 -6 -4 -1 -9 -7 -1 -6 -6 -9 -3 -5 -4 -3 -7 -3 -0 -8 -4 -6 -9 -0 -2 -9 -8 -1 -7 -2 -5 -3 -3 -7 -9 -3 -9 -5 -9 -9 -2 -8 -2 -6 -1 -1 -8 -2 -2 -9 -6 -9 -8 -5 -1 -8 -1 -8 -0 -6 -0 -3 -9 -3 -3 -6 -9 -3 -2 -0 -8 -3 -0 -1 -9 -6 -0 -8 -0 -1 -5 -7 -1 -3 -5 -5 -8 -0 -6 -2 -9 -6 -8 -2 -0 -7 -1 -2 -3 -1 -2 -4 -3 -8 -7 -3 -5 -0 -9 -4 -2 -2 -2 -9 -5 -9 -6 -8 -2 -2 -2 -1 -1 -2 -2 -8 -8 -5 -3 -9 -9 -0 -3 -1 -5 -3 -3 -0 -7 -8 -9 -5 -6 -0 -1 -7 -7 -6 -1 -3 -1 -2 -1 -4 -0 -9 -7 -0 -3 -7 -9 -8 -9 -6 -3 -1 -5 -8 -1 -9 -1 -0 -6 -6 -2 -5 -6 -1 -7 -1 -7 -0 -3 -3 -7 -9 -2 -0 -6 -8 -0 -1 -1 -1 -7 -7 -3 -3 -6 -4 -6 -9 -6 -0 -9 -1 -3 -3 -6 -7 -2 -1 -7 -5 -7 -6 -6 -7 -8 -1 -6 -3 -1 -0 -5 -9 -9 -9 -4 -6 -6 -1 -7 -8 -4 -4 -1 -3 -2 -9 -6 -8 -5 -9 -0 -2 -2 -7 -1 -3 -0 -6 -2 -6 -7 -9 -9 -3 -3 -9 -2 -1 -6 -5 -4 -0 -2 -4 -6 -2 -1 -6 -7 -5 -1 -9 -9 -5 -9 -4 -1 -5 -8 -1 -3 -5 -2 -7 -1 -2 -7 -1 -3 -4 -6 -9 -4 -9 -0 -9 -6 -9 -0 -8 -5 -9 -0 -3 -3 -0 -6 -8 -9 -0 -5 -9 -7 -6 -7 -2 -7 -7 -7 -1 -4 -8 -9 -6 -0 -2 -1 -5 -7 -9 -9 -0 -2 -0 -0 -2 -3 -6 -0 -2 -3 -2 -9 -1 -9 -2 -6 -4 -0 -9 -2 -4 -3 -1 -0 -2 -7 -6 -2 -5 -3 -7 -9 -3 -4 -0 -8 -9 -8 -7 -5 -1 -3 -5 -7 -9 -3 -3 -5 -7 -1 -2 -7 -5 -1 -5 -2 -5 -9 -8 -1 -9 -6 -7 -7 -2 -8 -3 -1 -7 -5 -9 -2 -6 -7 -3 -5 -4 -0 -7 -2 -4 -8 -2 -5 -1 -9 -8 -5 -1 -6 -3 -4 -9 -2 -6 -8 -4 -7 -1 -4 -4 -5 -6 -9 -4 -4 -2 -6 -3 -2 -7 -7 -2 -7 -1 -1 -7 -4 -0 -6 -2 -3 -0 -9 -9 -2 -7 -1 -6 -4 -1 -6 -7 -4 -1 -8 -7 -5 -4 -9 -2 -1 -4 -6 -6 -2 -7 -9 -5 -3 -4 -4 -8 -5 -7 -4 -5 -6 -6 -1 -3 -5 -6 -6 -2 -8 -2 -6 -8 -5 -3 -0 -0 -9 -8 -0 -1 -2 -9 -5 -3 -0 -9 -2 -9 -6 -1 -9 -7 -5 -8 -7 -0 -6 -3 -5 -3 -7 -0 -0 -9 -1 -6 -5 -1 -1 -5 -3 -4 -0 -3 -3 -1 -2 -8 -2 -7 -8 -9 -9 -7 -9 -1 -8 -8 -4 -4 -8 -4 -8 -5 -5 -7 -4 -9 -0 -3 -6 -1 -2 -4 -6 -2 -1 -1 -0 -7 -1 -5 -9 -3 -0 -5 -1 -7 -6 -1 -5 -2 -1 -1 -3 -7 -0 -8 -2 -4 -2 -5 -0 -3 -5 -9 -1 -3 -9 -5 -0 -0 -3 -6 -9 -0 -4 -5 -4 -1 -6 -2 -8 -1 -1 -4 -3 -8 -0 -7 -6 -6 -8 -5 -0 -5 -5 -6 -8 -4 -1 -2 -0 -3 -9 -6 -7 -8 -3 -9 -7 -8 -9 -6 -1 -3 -3 -4 -8 -3 -0 -1 -9 -1 -3 -0 -8 -6 -5 -4 -1 -7 -8 -3 -1 -9 -7 -8 -2 -6 -1 -0 -4 -0 -3 -5 -2 -9 -8 -1 -9 -2 -5 -2 -0 -9 -8 -3 -9 -0 -0 -6 -6 -7 -2 -7 -2 -3 -7 -9 -8 -3 -8 -8 -9 -6 -1 -8 -7 -2 -9 -6 -6 -4 -3 -1 -1 -4 -2 -1 -7 -5 -4 -9 -9 -2 -4 -5 -9 -4 -7 -1 -6 -6 -6 -2 -8 -4 -1 -5 -3 -7 -8 -3 -1 -3 -5 -0 -3 -6 -5 -7 -9 -9 -3 -0 -2 -5 -7 -8 -4 -7 -3 -7 -6 -6 -8 -3 -1 -4 -2 -2 -4 -9 -5 -1 -6 -6 -6 -7 -7 -8 -9 -0 -3 -4 -5 -0 -1 -6 -2 -1 -0 -9 -3 -8 -5 -5 -8 -8 -7 -0 -5 -7 -9 -6 -5 -6 -2 -2 -5 -8 -8 -5 -2 -9 -4 -6 -3 -8 -4 -4 -6 -6 -0 -4 -2 -5 -5 -1 -3 -9 -6 -2 -4 -5 -1 -1 -2 -7 -3 -6 -4 -2 -2 -4 -0 -1 -6 -6 -1 -7 -7 -2 -6 -5 -7 -4 -2 -8 -4 -9 -9 -2 -6 -1 -8 -1 -5 -0 -9 -3 -4 -2 -9 -9 -8 -3 -3 -4 -6 -9 -2 -6 -3 -3 -4 -4 -1 -1 -9 -5 -5 -1 -6 -1 -0 -0 -2 -7 -1 -1 -3 -0 -5 -4 -2 -6 -7 -8 -5 -9 -9 -6 -2 -2 -3 -6 -6 -2 -9 -0 -3 -6 -9 -5 -7 -1 -1 -7 -8 -2 -9 -7 -7 -9 -9 -5 -6 -9 -9 -1 -5 -5 -1 -8 -0 -7 -8 -0 -5 -9 -6 -8 -6 -2 -6 -6 -7 -0 -0 -5 -9 -1 -7 -1 -1 -3 -1 -1 -5 -5 -8 -3 -2 -3 -2 -9 -4 -6 -3 -7 -1 -5 -7 -8 -4 -8 -3 -0 -3 -9 -8 -0 -2 -8 -7 -9 -6 -3 -4 -9 -3 -6 -1 -7 -5 -9 -4 -6 -9 -2 -1 -7 -5 -7 -6 -4 -3 -6 -6 -9 -6 -5 -1 -5 -9 -6 -5 -0 -4 -1 -4 -2 -7 -8 -9 -8 -8 -0 -6 -2 -4 -9 -9 -9 -3 -3 -5 -3 -1 -0 -2 -7 -4 -1 -1 -8 -2 -9 -7 -2 -5 -0 -6 -8 -1 -5 -8 -4 -4 -8 -5 -3 -2 -1 -6 -7 -4 -4 -9 -2 -5 -8 -5 -3 -7 -7 -3 -3 -5 -7 -0 -7 -9 -9 -1 -6 -1 -9 -1 -9 -9 -7 -2 -2 -9 -7 -8 -0 -9 -9 -6 -7 -3 -5 -7 -7 -5 -9 -9 -0 -7 -8 -0 -6 -6 -5 -1 -8 -5 -9 -9 -5 -2 -8 -6 -8 -6 -7 -7 -7 -4 -4 -4 -1 -0 -6 -1 -6 -7 -1 -1 -6 -1 -7 -3 -7 -2 -6 -2 -9 -5 -0 -3 -2 -7 -6 -6 -9 -9 -1 -9 -2 -2 -6 -0 -3 -3 -6 -6 -1 -6 -1 -9 -8 -0 -0 -9 -3 -3 -9 -9 -3 -3 -5 -9 -1 -1 -8 -5 -8 -6 -2 -0 -6 -8 -0 -0 -2 -5 -5 -1 -1 -1 -8 -2 -4 -2 -1 -7 -9 -2 -9 -6 -2 -8 -2 -6 -5 -8 -8 -5 -0 -0 -0 -3 -2 -7 -7 -7 -2 -2 -1 -8 -1 -4 -4 -2 -7 -6 -8 -9 -7 -2 -7 -7 -5 -1 -8 -5 -5 -9 -3 -9 -7 -6 -0 -4 -8 -3 -6 -2 -4 -8 -3 -4 -5 -0 -9 -9 -0 -3 -5 -1 -1 -1 -9 -4 -8 -0 -8 -9 -2 -5 -2 -5 -1 -7 -0 -0 -2 -8 -1 -0 -4 -3 -9 -2 -5 -0 -7 -3 -6 -1 -7 -5 -3 -3 -2 -1 -6 -2 -4 -5 -6 -0 -6 -2 -1 -4 -7 -7 -0 -2 -1 -1 -5 -3 -7 -4 -0 -2 -4 -0 -2 -4 -2 -9 -3 -5 -5 -7 -6 -2 -6 -0 -5 -7 -9 -6 -4 -3 -2 -8 -2 -9 -5 -2 -5 -6 -0 -3 -0 -5 -5 -1 -5 -1 -9 -4 -5 -8 -1 -1 -5 -8 -4 -1 -7 -0 -4 -4 -1 -8 -7 -7 -4 -9 -3 -6 -3 -6 -2 -2 -8 -3 -1 -7 -3 -1 -4 -5 -4 -0 -8 -2 -8 -8 -3 -2 -8 -5 -4 -6 -3 -3 -3 -7 -1 -9 -6 -6 -7 -5 -9 -0 -2 -1 -4 -2 -4 -5 -1 -1 -6 -9 -7 -6 -7 -6 -9 -8 -4 -7 -9 -1 -4 -6 -2 -4 -3 -8 -8 -9 -7 -6 -3 -9 -1 -6 -3 -9 -0 -9 -6 -4 -2 -5 -6 -3 -5 -2 -0 -5 -7 -3 -9 -5 -5 -0 -0 -9 -3 -1 -9 -1 -1 -1 -4 -8 -6 -4 -4 -3 -0 -8 -9 -1 -4 -2 -4 -0 -1 -0 -3 -9 -0 -8 -8 -7 -0 -8 -8 -9 -6 -9 -5 -6 -6 -5 -9 -9 -6 -4 -2 -1 -5 -5 -2 -7 -0 -1 -0 -0 -9 -3 -2 -1 -6 -6 -7 -7 -5 -5 -2 -8 -3 -3 -2 -5 -8 -3 -3 -9 -9 -6 -4 -6 -1 -0 -9 -3 -6 -7 -5 -3 -2 -7 -7 -5 -6 -2 -3 -3 -6 -4 -6 -1 -2 -1 -7 -2 -2 -6 -6 -4 -4 -8 -6 -9 -5 -8 -5 -2 -8 -9 -8 -0 -9 -6 -9 -3 -2 -4 -0 -6 -6 -2 -4 -7 -8 -1 -3 -8 -1 -2 -7 -1 -3 -7 -9 -9 -4 -3 -4 -3 -7 -1 -2 -6 -8 -5 -1 -2 -1 -1 -0 -5 -6 -5 -2 -6 -2 -2 -3 -6 -9 -7 -4 -9 -0 -1 -1 -1 -1 -3 -5 -5 -1 -2 -3 -1 -2 -6 -1 -9 -0 -8 -0 -2 -1 -4 -4 -5 -7 -0 -8 -7 -8 -1 -3 -7 -2 -2 -2 -4 -2 -9 -3 -9 -2 -8 -3 -2 -5 -9 -4 -3 -7 -1 -0 -6 -9 -0 -9 -2 -0 -0 -5 -0 -5 -6 -0 -2 -7 -5 -0 -7 -4 -9 -9 -3 -6 -2 -9 -1 -3 -2 -3 -0 -0 -6 -5 -1 -7 -0 -6 -2 -0 -9 -9 -1 -5 -3 -5 -8 -9 -6 -7 -1 -5 -0 -1 -0 -0 -6 -4 -7 -7 -4 -9 -3 -8 -8 -9 -6 -7 -0 -1 -1 -3 -8 -7 -7 -4 -2 -1 -5 -7 -1 -7 -8 -2 -8 -0 -8 -3 -1 -0 -1 -3 -3 -6 -6 -6 -6 -1 -0 -8 -3 -7 -0 -5 -9 -6 -0 -2 -2 -5 -6 -1 -7 -5 -1 -7 -8 -1 -0 -4 -9 -3 -0 -2 -1 -3 -8 -3 -5 -7 -2 -8 -2 -1 -0 -2 -4 -5 -6 -7 -3 -8 -5 -0 -3 -5 -8 -1 -9 -4 -5 -8 -3 -9 -6 -1 -1 -6 -6 -4 -4 -5 -0 -2 -4 -2 -5 -9 -6 -8 -8 -5 -9 -0 -3 -0 -9 -2 -6 -3 -9 -3 -9 -6 -8 -9 -5 -3 -7 -2 -7 -1 -7 -4 -6 -7 -4 -6 -1 -5 -7 -9 -5 -6 -1 -2 -9 -3 -1 -8 -5 -1 -4 -1 -1 -8 -5 -8 -2 -2 -5 -2 -7 -5 -3 -6 -7 -8 -9 -6 -6 -1 -0 -9 -0 -0 -9 -3 -4 -7 -5 -5 -6 -9 -9 -2 -3 -9 -7 -3 -1 -6 -0 -0 -0 -2 -8 -6 -3 -6 -6 -6 -0 -2 -7 -3 -8 -1 -9 -6 -7 -9 -6 -7 -0 -1 -6 -4 -8 -4 -8 -5 -3 -5 -5 -8 -2 -9 -3 -2 -4 -7 -4 -2 -6 -3 -7 -6 -2 -0 -3 -4 -5 -6 -8 -9 -1 -4 -5 -1 -9 -1 -5 -2 -6 -7 -7 -4 -6 -5 -4 -6 -0 -0 -7 -0 -5 -8 -3 -6 -3 -8 -8 -3 -6 -1 -7 -9 -9 -1 -8 -8 -1 -4 -1 -9 -5 -9 -1 -9 -8 -2 -6 -4 -8 -5 -1 -7 -9 -8 -1 -6 -9 -5 -6 -1 -1 -2 -1 -0 -7 -0 -7 -1 -4 -4 -2 -6 -3 -1 -9 -3 -6 -5 -5 -5 -7 -6 -5 -0 -7 -8 -3 -5 -4 -3 -4 -3 -7 -9 -6 -2 -6 -0 -2 -5 -1 -1 -1 -2 -5 -3 -9 -9 -8 -9 -6 -9 -7 -5 -5 -2 -0 -1 -7 -4 -7 -9 -3 -2 -3 -5 -1 -9 -5 -6 -9 -6 -5 -1 -4 -8 -2 -8 -9 -6 -6 -8 -3 -3 -4 -2 -2 -1 -0 -1 -8 -0 -7 -1 -9 -3 -7 -1 -0 -4 -3 -6 -7 -8 -3 -2 -7 -7 -6 -5 -4 -7 -6 -9 -8 -6 -1 -1 -2 -4 -6 -1 -3 -1 -8 -1 -9 -4 -3 -9 -3 -5 -4 -3 -7 -9 -9 -4 -0 -8 -2 -5 -8 -9 -0 -9 -1 -9 -4 -3 -6 -8 -9 -3 -9 -2 -7 -4 -0 -8 -9 -3 -9 -7 -5 -0 -2 -5 -2 -2 -8 -2 -0 -5 -4 -7 -3 -2 -4 -3 -0 -1 -2 -5 -1 -3 -1 -2 -4 -7 -3 -6 -2 -4 -9 -3 -7 -3 -6 -1 -5 -2 -5 -1 -5 -6 -8 -2 -2 -2 -1 -5 -6 -3 -9 -1 -7 -8 -0 -6 -7 -4 -6 -0 -3 -8 -6 -1 -6 -4 -7 -6 -7 -3 -4 -1 -7 -4 -4 -6 -6 -9 -5 -7 -9 -3 -8 -2 -5 -4 -5 -4 -0 -0 -9 -7 -7 -5 -7 -4 -5 -9 -7 -9 -9 -1 -8 -9 -9 -5 -7 -1 -2 -0 -1 -9 -6 -5 -9 -0 -4 -8 -0 -5 -9 -3 -3 -7 -7 -0 -7 -0 -5 -4 -2 -5 -7 -0 -3 -4 -4 -1 -0 -0 -9 -9 -6 -4 -4 -1 -1 -0 -0 -9 -9 -7 -4 -7 -2 -1 -8 -4 -4 -4 -5 -6 -6 -2 -1 -1 -4 -2 -1 -8 -7 -1 -7 -8 -3 -3 -3 -0 -0 -5 -1 -2 -9 -9 -0 -0 -8 -7 -6 -6 -1 -9 -7 -2 -9 -7 -8 -1 -9 -1 -5 -2 -8 -8 -9 -9 -3 -8 -5 -5 -3 -6 -8 -3 -2 -6 -1 -4 -9 -6 -4 -8 -4 -3 -1 -8 -1 -3 -4 -5 -6 -5 -1 -9 -2 -6 -5 -1 -4 -7 -3 -0 -0 -6 -1 -0 -7 -7 -5 -8 -7 -4 -7 -9 -0 -0 -8 -1 -3 -9 -2 -1 -4 -7 -7 -1 -1 -8 -2 -9 -0 -0 -3 -1 -7 -6 -6 -3 -6 -1 -4 -8 -9 -4 -9 -3 -6 -6 -5 -8 -8 -8 -8 -9 -3 -8 -3 -7 -0 -0 -4 -0 -7 -7 -4 -8 -9 -2 -8 -3 -3 -1 -5 -5 -1 -1 -5 -1 -9 -3 -3 -1 -4 -7 -1 -4 -7 -3 -5 -1 -6 -9 -5 -3 -8 -2 -8 -8 -0 -5 -6 -0 -6 -0 -0 -3 -6 -2 -2 -6 -8 -1 -7 -1 -5 -3 -4 -6 -2 -7 -6 -8 -1 -2 -4 -1 -2 -3 -5 -6 -7 -8 -9 -4 -4 -6 -2 -7 -8 -5 -1 -7 -1 -6 -2 -1 -1 -2 -2 -8 -4 -0 -7 -9 -1 -7 -6 -7 -1 -2 -2 -3 -5 -2 -4 -1 -9 -4 -9 -8 -0 -4 -3 -9 -3 -9 -1 -4 -7 -5 -8 -6 -9 -9 -9 -9 -4 -1 -4 -3 -3 -5 -6 -6 -0 -2 -9 -2 -0 -4 -2 -6 -9 -9 -6 -3 -6 -2 -1 -5 -6 -8 -0 -2 -8 -4 -5 -6 -7 -5 -2 -6 -8 -0 -5 -1 -8 -9 -7 -3 -0 -6 -8 -3 -4 -5 -3 -2 -4 -6 -9 -4 -8 -2 -8 -9 -9 -0 -6 -0 -2 -1 -1 -4 -1 -7 -2 -3 -2 -1 -9 -6 -0 -3 -8 -3 -3 -9 -2 -0 -7 -7 -2 -0 -8 -6 -1 -1 -1 -6 -1 -2 -4 -1 -8 -0 -9 -8 -3 -5 -0 -2 -1 -8 -8 -1 -9 -7 -8 -9 -7 -9 -9 -4 -3 -1 -3 -7 -0 -8 -9 -1 -7 -0 -4 -0 -5 -0 -0 -5 -7 -6 -3 -2 -9 -8 -2 -9 -7 -2 -8 -1 -9 -1 -4 -9 -0 -7 -6 -8 -2 -1 -9 -1 -9 -0 -5 -5 -3 -6 -2 -6 -5 -0 -6 -4 -0 -1 -6 -1 -2 -6 -4 -6 -4 -9 -6 -9 -5 -9 -8 -5 -6 -0 -0 -1 -4 -9 -1 -3 -4 -1 -6 -4 -5 -1 -9 -8 -4 -6 -4 -1 -8 -2 -3 -7 -2 -8 -3 -3 -1 -6 -3 -1 -4 -2 -2 -1 -6 -7 -9 -2 -0 -0 -7 -4 -5 -4 -4 -5 -8 -6 -1 -8 -1 -8 -4 -6 -4 -1 -2 -9 -9 -6 -6 -9 -7 -6 -4 -6 -3 -9 -5 -0 -8 -6 -2 -1 -7 -6 -4 -8 -3 -4 -1 -4 -6 -1 -9 -1 -8 -0 -6 -2 -1 -2 -0 -9 -8 -6 -2 -4 -4 -7 -7 -8 -8 -3 -7 -6 -3 -5 -9 -5 -2 -7 -4 -6 -2 -3 -3 -0 -1 -3 -8 -8 -9 -0 -0 -6 -8 -3 -8 -9 -2 -1 -6 -3 -6 -9 -3 -1 -9 -7 -4 -8 -7 -9 -4 -8 -0 -3 -8 -7 -1 -3 -0 -5 -4 -4 -2 -4 -9 -5 -4 -1 -9 -3 -9 -7 -6 -6 -1 -5 -2 -9 -7 -7 -4 -9 -5 -7 -8 -5 -7 -6 -7 -4 -3 -0 -4 -7 -5 -8 -5 -1 -0 -0 -4 -7 -9 -0 -7 -2 -8 -8 -0 -1 -9 -5 -9 -5 -5 -4 -7 -4 -9 -8 -9 -1 -3 -6 -4 -0 -5 -7 -7 -2 -0 -2 -4 -7 -2 -2 -1 -4 -4 -6 -8 -6 -5 -0 -3 -8 -4 -6 -7 -6 -2 -1 -8 -4 -5 -2 -1 -0 -0 -7 -4 -0 -9 -9 -1 -7 -2 -1 -5 -5 -1 -8 -4 -5 -5 -7 -6 -8 -9 -0 -6 -6 -1 -7 -5 -4 -3 -8 -6 -9 -2 -1 -1 -4 -9 -5 -8 -1 -0 -6 -0 -0 -4 -2 -3 -6 -7 -4 -1 -8 -4 -1 -2 -0 -8 -6 -1 -5 -2 -2 -5 -7 -4 -6 -9 -6 -1 -9 -0 -8 -9 -4 -4 -7 -1 -3 -1 -4 -8 -9 -5 -9 -5 -6 -4 -9 -4 -7 -0 -1 -6 -0 -1 -8 -0 -6 -6 -1 -7 -3 -7 -9 -0 -9 -6 -9 -7 -3 -0 -2 -1 -7 -0 -0 -2 -1 -1 -6 -6 -7 -0 -2 -1 -8 -5 -5 -4 -3 -6 -1 -4 -0 -2 -4 -0 -1 -5 -4 -1 -0 -8 -2 -7 -4 -3 -3 -3 -1 -9 -2 -0 -6 -0 -6 -7 -9 -3 -7 -9 -9 -5 -7 -1 -3 -6 -9 -1 -7 -2 -7 -3 -9 -3 -7 -1 -4 -9 -3 -1 -5 -3 -1 -4 -1 -0 -9 -7 -3 -2 -3 -7 -7 -8 -7 -7 -6 -4 -7 -2 -6 -5 -6 -4 -0 -4 -8 -1 -1 -3 -9 -0 -1 -2 -2 -5 -8 -3 -4 -8 -7 -4 -2 -3 -1 -3 -8 -4 -9 -4 -0 -9 -6 -9 -1 -0 -4 -9 -1 -0 -2 -1 -7 -3 -1 -6 -4 -7 -8 -7 -8 -5 -2 -4 -7 -7 -2 -2 -8 -4 -1 -7 -5 -3 -2 -1 -6 -5 -1 -9 -8 -1 -2 -6 -1 -8 -2 -5 -9 -2 -2 -4 -0 -2 -0 -2 -9 -9 -4 -4 -7 -7 -5 -8 -9 -1 -5 -0 -6 -8 -1 -0 -0 -9 -4 -9 -2 -5 -6 -2 -9 -1 -9 -1 -8 -3 -0 -6 -6 -9 -2 -1 -4 -5 -1 -2 -2 -1 -3 -0 -5 -0 -7 -9 -5 -8 -7 -2 -2 -6 -6 -8 -8 -0 -0 -4 -9 -5 -1 -5 -3 -2 -9 -2 -2 -9 -6 -8 -2 -0 -0 -9 -2 -3 -1 -5 -0 -8 -3 -2 -8 -2 -4 -6 -3 -2 -6 -5 -0 -7 -5 -8 -0 -2 -9 -4 -5 -6 -0 -9 -9 -9 -4 -7 -9 -5 -9 -2 -1 -6 -1 -5 -9 -4 -1 -1 -5 -1 -3 -4 -4 -0 -9 -0 -4 -9 -3 -2 -3 -0 -4 -7 -1 -1 -5 -6 -1 -7 -0 -3 -6 -1 -9 -0 -3 -5 -3 -1 -2 -0 -5 -9 -1 -9 -7 -0 -6 -7 -1 -8 -8 -7 -2 -1 -5 -6 -0 -3 -6 -0 -1 -3 -6 -4 -9 -7 -0 -4 -4 -1 -7 -0 -3 -8 -6 -8 -1 -4 -0 -7 -2 -8 -8 -8 -8 -1 -9 -9 -0 -6 -0 -5 -5 -7 -3 -8 -3 -7 -1 -6 -2 -9 -6 -5 -0 -4 -7 -7 -8 -9 -0 -6 -3 -5 -2 -6 -0 -0 -9 -7 -9 -2 -4 -5 -0 -6 -4 -1 -2 -9 -8 -7 -7 -8 -8 -9 -1 -9 -7 -6 -7 -3 -3 -2 -4 -3 -9 -8 -6 -2 -5 -7 -9 -9 -5 -4 -1 -2 -0 -1 -4 -8 -2 -2 -5 -7 -1 -8 -6 -7 -4 -0 -3 -2 -1 -4 -3 -5 -9 -0 -7 -1 -1 -3 -9 -8 -9 -1 -7 -9 -3 -3 -0 -6 -6 -6 -2 -2 -9 -5 -2 -4 -6 -5 -3 -9 -2 -5 -1 -7 -5 -6 -8 -5 -9 -6 -8 -1 -0 -1 -8 -2 -8 -9 -2 -9 -6 -0 -5 -3 -6 -3 -9 -2 -0 -9 -9 -0 -3 -1 -4 -7 -8 -2 -9 -5 -5 -2 -6 -0 -9 -7 -6 -2 -1 -3 -4 -4 -7 -7 -8 -9 -6 -5 -8 -9 -9 -9 -4 -0 -3 -2 -6 -3 -5 -4 -9 -5 -4 -4 -1 -4 -2 -0 -6 -8 -5 -9 -7 -4 -7 -9 -5 -3 -3 -0 -2 -3 -4 -4 -2 -6 -8 -0 -5 -9 -1 -7 -5 -3 -1 -6 -1 -6 -1 -6 -4 -3 -9 -4 -6 -3 -1 -1 -6 -9 -3 -7 -2 -3 -5 -5 -5 -6 -0 -6 -1 -7 -5 -8 -0 -8 -3 -1 -3 -9 -2 -7 -0 -8 -0 -0 -3 -0 -6 -5 -1 -5 -6 -2 -9 -7 -5 -6 -4 -3 -6 -2 -1 -9 -3 -5 -9 -4 -3 -6 -8 -1 -1 -5 -8 -3 -4 -2 -2 -1 -1 -4 -2 -8 -1 -8 -9 -0 -8 -1 -8 -1 -9 -9 -0 -0 -4 -7 -1 -0 -8 -1 -3 -9 -9 -7 -1 -2 -9 -5 -6 -1 -3 -8 -6 -1 -9 -3 -8 -2 -5 -7 -1 -9 -0 -0 -7 -9 -5 -9 -5 -6 -3 -6 -8 -4 -4 -9 -5 -8 -8 -5 -1 -9 -6 -7 -0 -4 -9 -5 -2 -9 -2 -1 -0 -9 -7 -7 -7 -6 -0 -1 -9 -6 -0 -1 -9 -1 -2 -9 -3 -1 -0 -3 -6 -5 -7 -6 -6 -8 -1 -8 -1 -7 -3 -3 -6 -1 -5 -5 -0 -1 -2 -9 -1 -4 -1 -9 -6 -1 -7 -5 -7 -6 -3 -2 -4 -8 -7 -8 -0 -2 -1 -6 -5 -4 -0 -0 -4 -1 -1 -1 -1 -4 -8 -7 -9 -2 -9 -1 -6 -4 -1 -2 -2 -1 -1 -7 -3 -3 -4 -7 -9 -7 -0 -0 -4 -1 -1 -3 -6 -5 -0 -1 -4 -6 -6 -7 -8 -9 -7 -5 -2 -6 -1 -1 -3 -6 -8 -0 -2 -5 -7 -8 -5 -0 -9 -4 -4 -3 -1 -2 -9 -1 -3 -7 -6 -9 -1 -9 -3 -7 -1 -7 -1 -9 -3 -6 -0 -1 -5 -6 -6 -2 -3 -9 -7 -6 -6 -9 -7 -6 -6 -2 -4 -1 -8 -1 -2 -3 -7 -9 -5 -9 -4 -1 -0 -3 -1 -2 -7 -5 -0 -2 -4 -1 -8 -5 -4 -0 -0 -0 -2 -7 -0 -8 -8 -4 -6 -3 -4 -0 -6 -9 -1 -7 -8 -3 -1 -6 -3 -5 -9 -9 -1 -6 -1 -1 -4 -0 -9 -2 -4 -7 -9 -2 -6 -3 -0 -6 -6 -1 -6 -9 -9 -3 -7 -5 -5 -7 -5 -0 -9 -4 -1 -8 -8 -1 -1 -4 -7 -8 -6 -1 -2 -9 -8 -1 -5 -3 -2 -7 -5 -1 -0 -1 -0 -3 -3 -1 -5 -8 -8 -9 -3 -1 -3 -8 -6 -5 -1 -6 -9 -2 -8 -7 -9 -0 -8 -5 -4 -9 -5 -5 -8 -9 -8 -9 -9 -9 -1 -0 -9 -6 -7 -0 -6 -1 -3 -0 -6 -8 -2 -0 -1 -5 -6 -9 -8 -2 -5 -3 -3 -8 -1 -2 -3 -2 -0 -5 -2 -5 -1 -1 -9 -3 -9 -1 -4 -7 -9 -4 -7 -6 -1 -9 -7 -7 -1 -5 -9 -2 -8 -6 -7 -7 -1 -5 -4 -4 -0 -9 -7 -1 -6 -3 -0 -2 -7 -2 -7 -1 -3 -2 -4 -2 -1 -6 -8 -5 -1 -0 -5 -7 -1 -7 -3 -9 -8 -0 -9 -2 -9 -9 -6 -6 -3 -2 -6 -9 -5 -5 -4 -1 -1 -4 -6 -0 -1 -5 -8 -0 -0 -3 -9 -8 -1 -0 -9 -2 -6 -2 -0 -6 -8 -7 -0 -7 -5 -7 -5 -1 -1 -5 -7 -7 -7 -3 -4 -1 -0 -6 -9 -9 -6 -9 -1 -7 -4 -5 -8 -9 -9 -1 -1 -9 -9 -1 -7 -7 -6 -5 -5 -2 -7 -1 -3 -6 -8 -5 -2 -7 -1 -4 -0 -8 -5 -8 -5 -1 -2 -4 -5 -5 -2 -1 -3 -5 -2 -2 -9 -4 -9 -9 -5 -9 -1 -3 -2 -9 -6 -2 -2 -0 -7 -5 -7 -3 -4 -9 -4 -1 -2 -9 -2 -2 -8 -1 -0 -0 -9 -0 -6 -2 -4 -1 -0 -9 -7 -1 -1 -6 -9 -0 -8 -2 -9 -5 -0 -9 -3 -0 -7 -2 -7 -6 -0 -1 -1 -1 -7 -6 -1 -7 -7 -3 -8 -5 -0 -9 -1 -0 -8 -3 -9 -9 -5 -2 -6 -5 -0 -5 -2 -7 -3 -3 -4 -4 -7 -2 -1 -9 -3 -4 -5 -2 -7 -4 -5 -5 -7 -4 -1 -8 -4 -3 -7 -1 -2 -3 -0 -9 -1 -4 -3 -9 -9 -1 -7 -5 -6 -8 -4 -1 -5 -5 -2 -2 -2 -8 -4 -0 -7 -6 -4 -3 -2 -3 -1 -7 -6 -7 -6 -8 -9 -0 -2 -3 -6 -9 -6 -9 -4 -5 -9 -1 -9 -7 -1 -5 -9 -7 -2 -7 -6 -7 -8 -1 -6 -1 -9 -9 -7 -2 -1 -1 -0 -5 -5 -5 -9 -1 -4 -9 -2 -1 -7 -6 -6 -2 -4 -2 -3 -1 -5 -2 -9 -0 -2 -7 -3 -7 -8 -2 -0 -7 -2 -7 -2 -9 -1 -2 -0 -2 -9 -3 -0 -6 -2 -8 -0 -3 -7 -6 -1 -9 -0 -3 -1 -4 -5 -7 -9 -3 -1 -9 -5 -0 -4 -7 -2 -2 -1 -9 -5 -7 -9 -6 -2 -6 -7 -7 -8 -0 -5 -2 -7 -0 -2 -0 -2 -0 -2 -4 -2 -5 -9 -7 -5 -2 -7 -5 -1 -4 -2 -5 -6 -1 -9 -8 -8 -9 -4 -1 -5 -0 -8 -6 -6 -6 -5 -0 -0 -6 -9 -5 -4 -4 -8 -2 -2 -2 -1 -7 -7 -8 -0 -0 -1 -6 -5 -4 -2 -0 -2 -5 -7 -8 -5 -2 -4 -4 -9 -4 -4 -6 -6 -9 -0 -3 -9 -1 -3 -2 -4 -0 -0 -1 -1 -7 -6 -2 -8 -1 -2 -7 -5 -1 -8 -0 -1 -5 -7 -8 -5 -9 -1 -2 -7 -7 -0 -0 -1 -7 -3 -0 -3 -1 -4 -1 -3 -8 -3 -7 -3 -9 -1 -7 -7 -1 -2 -6 -5 -8 -0 -3 -2 -9 -6 -5 -4 -6 -7 -0 -3 -4 -6 -3 -5 -2 -7 -7 -3 -5 -4 -9 -0 -3 -1 -5 -3 -1 -2 -0 -2 -4 -8 -9 -4 -2 -9 -7 -9 -9 -5 -3 -4 -2 -6 -6 -5 -1 -9 -9 -7 -1 -7 -7 -4 -4 -8 -8 -7 -6 -1 -4 -4 -9 -0 -9 -6 -7 -0 -9 -9 -1 -9 -6 -7 -5 -7 -6 -0 -5 -9 -9 -9 -9 -2 -4 -5 -7 -0 -8 -6 -1 -8 -4 -6 -2 -7 -2 -7 -9 -9 -1 -4 -7 -1 -7 -6 -6 -1 -9 -0 -1 -3 -0 -1 -3 -2 -6 -5 -3 -9 -3 -9 -9 -3 -3 -0 -7 -5 -9 -6 -6 -4 -6 -5 -7 -3 -6 -1 -6 -8 -6 -7 -4 -1 -6 -0 -4 -2 -2 -5 -8 -4 -1 -9 -2 -9 -9 -7 -9 -1 -5 -7 -1 -8 -8 -6 -6 -7 -6 -0 -7 -6 -3 -1 -0 -7 -9 -5 -7 -8 -1 -0 -9 -9 -9 -0 -0 -7 -7 -4 -9 -7 -1 -5 -7 -1 -3 -3 -0 -3 -9 -1 -7 -0 -2 -0 -1 -5 -0 -3 -7 -9 -2 -4 -4 -9 -8 -8 -0 -4 -3 -6 -1 -9 -4 -8 -9 -6 -8 -9 -4 -7 -1 -5 -9 -2 -3 -8 -6 -5 -4 -5 -0 -1 -9 -0 -5 -8 -1 -1 -5 -4 -8 -2 -5 -1 -5 -1 -1 -8 -8 -0 -8 -9 -8 -9 -3 -2 -0 -8 -9 -9 -0 -6 -0 -1 -9 -9 -9 -4 -1 -4 -9 -1 -6 -5 -1 -8 -3 -1 -7 -9 -6 -3 -9 -5 -7 -7 -5 -4 -8 -4 -5 -2 -4 -1 -9 -3 -1 -1 -3 -7 -9 -0 -4 -9 -4 -9 -0 -0 -3 -1 -4 -2 -0 -4 -1 -0 -9 -1 -9 -4 -9 -1 -4 -7 -8 -8 -1 -5 -9 -3 -0 -5 -9 -5 -9 -5 -0 -9 -5 -1 -9 -8 -5 -9 -2 -1 -9 -9 -6 -3 -8 -1 -7 -9 -7 -6 -3 -3 -1 -3 -1 -0 -1 -8 -1 -1 -9 -1 -5 -0 -6 -9 -0 -0 -6 -9 -0 -1 -7 -2 -7 -6 -7 -7 -7 -7 -2 -3 -8 -1 -0 -9 -0 -2 -0 -7 -3 -7 -4 -5 -7 -6 -1 -1 -6 -9 -6 -7 -2 -6 -1 -0 -8 -2 -9 -8 -4 -5 -2 -6 -2 -1 -5 -3 -1 -1 -6 -3 -8 -2 -6 -7 -6 -0 -9 -5 -2 -9 -6 -0 -5 -8 -0 -1 -0 -8 -7 -2 -9 -6 -9 -0 -2 -4 -1 -2 -0 -1 -4 -7 -6 -6 -9 -1 -9 -0 -7 -1 -1 -8 -8 -5 -2 -9 -1 -2 -0 -0 -7 -5 -9 -0 -5 -2 -6 -7 -1 -3 -2 -1 -9 -9 -6 -0 -9 -1 -8 -8 -8 -1 -8 -8 -3 -4 -1 -5 -6 -2 -1 -8 -6 -9 -6 -3 -6 -8 -1 -5 -0 -5 -0 -0 -9 -8 -1 -9 -0 -1 -8 -9 -2 -5 -9 -0 -1 -4 -2 -3 -4 -5 -0 -0 -3 -0 -6 -6 -1 -9 -1 -4 -9 -8 -2 -0 -6 -1 -5 -6 -4 -9 -4 -1 -0 -4 -1 -7 -0 -7 -3 -6 -9 -9 -6 -2 -6 -8 -5 -0 -0 -3 -1 -0 -0 -2 -5 -5 -1 -8 -1 -9 -1 -6 -9 -9 -9 -3 -2 -0 -9 -3 -1 -6 -2 -3 -6 -1 -1 -6 -7 -9 -3 -9 -5 -5 -8 -6 -3 -9 -4 -0 -3 -7 -8 -5 -3 -1 -5 -0 -7 -9 -0 -4 -0 -0 -4 -8 -5 -1 -9 -7 -0 -0 -7 -4 -5 -8 -6 -9 -6 -7 -7 -1 -6 -8 -3 -9 -7 -6 -3 -0 -1 -9 -6 -9 -3 -9 -2 -3 -0 -1 -2 -8 -2 -1 -3 -9 -0 -3 -8 -9 -7 -7 -9 -2 -9 -7 -5 -2 -4 -5 -5 -7 -4 -5 -9 -4 -7 -5 -6 -0 -3 -6 -5 -0 -4 -8 -3 -9 -2 -7 -0 -7 -4 -2 -9 -3 -2 -0 -6 -2 -4 -0 -1 -4 -0 -6 -7 -0 -0 -5 -8 -2 -1 -3 -7 -1 -2 -6 -3 -9 -7 -0 -3 -9 -5 -4 -4 -9 -2 -8 -0 -0 -9 -7 -3 -3 -5 -9 -2 -7 -2 -9 -5 -1 -1 -3 -6 -1 -2 -2 -5 -4 -2 -1 -3 -7 -3 -7 -5 -6 -9 -7 -4 -9 -0 -8 -8 -6 -7 -1 -5 -7 -9 -9 -0 -9 -3 -6 -1 -7 -2 -4 -3 -3 -9 -7 -3 -6 -0 -0 -1 -3 -0 -5 -2 -8 -9 -7 -6 -2 -5 -8 -0 -9 -7 -6 -7 -6 -2 -3 -3 -7 -7 -3 -2 -0 -3 -4 -6 -8 -2 -9 -1 -1 -6 -9 -1 -1 -8 -1 -8 -3 -0 -6 -3 -2 -4 -3 -9 -2 -0 -9 -5 -9 -6 -2 -7 -1 -8 -0 -3 -1 -9 -1 -0 -1 -9 -5 -9 -2 -2 -2 -1 -5 -9 -2 -2 -6 -8 -3 -9 -1 -9 -1 -8 -3 -2 -9 -7 -9 -1 -2 -2 -6 -1 -1 -9 -1 -5 -2 -7 -3 -0 -5 -6 -8 -3 -6 -2 -7 -9 -0 -8 -1 -7 -4 -6 -9 -8 -3 -7 -5 -2 -7 -6 -6 -7 -7 -6 -6 -2 -0 -8 -9 -6 -4 -7 -3 -5 -6 -8 -8 -8 -0 -6 -6 -0 -0 -0 -1 -0 -6 -3 -4 -2 -0 -6 -2 -0 -9 -8 -1 -6 -2 -5 -1 -9 -8 -8 -9 -0 -8 -1 -6 -4 -8 -5 -1 -5 -0 -6 -1 -0 -2 -6 -7 -5 -5 -4 -2 -7 -5 -5 -2 -9 -3 -1 -9 -3 -6 -1 -7 -1 -3 -4 -6 -7 -9 -7 -1 -8 -0 -1 -8 -5 -2 -1 -1 -9 -4 -9 -7 -4 -1 -5 -3 -0 -1 -0 -6 -7 -3 -7 -5 -0 -7 -7 -7 -7 -1 -4 -9 -6 -9 -9 -5 -7 -1 -5 -8 -9 -4 -1 -6 -7 -3 -4 -4 -9 -5 -6 -7 -4 -7 -1 -9 -0 -4 -5 -6 -3 -5 -3 -7 -1 -5 -7 -9 -7 -0 -3 -1 -7 -2 -7 -0 -1 -5 -2 -6 -7 -5 -7 -9 -6 -7 -2 -8 -2 -5 -6 -6 -5 -9 -7 -8 -2 -4 -9 -6 -4 -4 -9 -6 -7 -1 -8 -6 -0 -3 -2 -7 -1 -9 -5 -2 -3 -5 -5 -7 -9 -7 -9 -2 -7 -8 -5 -2 -7 -5 -0 -1 -1 -8 -0 -8 -5 -6 -3 -0 -8 -4 -9 -6 -4 -1 -0 -9 -3 -8 -4 -2 -8 -1 -1 -6 -5 -1 -2 -7 -8 -6 -2 -8 -7 -8 -9 -7 -7 -0 -2 -3 -0 -8 -9 -8 -4 -9 -2 -9 -7 -7 -9 -1 -3 -3 -3 -8 -0 -6 -2 -7 -7 -2 -5 -2 -9 -8 -0 -3 -3 -4 -4 -3 -2 -5 -2 -8 -9 -7 -9 -6 -1 -0 -4 -5 -5 -2 -7 -4 -9 -4 -6 -9 -7 -9 -2 -1 -8 -8 -3 -5 -2 -9 -1 -2 -7 -1 -4 -4 -6 -5 -7 -2 -6 -4 -3 -1 -6 -9 -0 -4 -8 -1 -1 -0 -0 -9 -6 -1 -2 -4 -0 -7 -3 -2 -1 -0 -3 -2 -3 -9 -7 -4 -0 -7 -5 -5 -4 -1 -4 -1 -9 -0 -0 -3 -1 -0 -6 -1 -1 -7 -7 -6 -5 -0 -5 -5 -9 -2 -2 -5 -9 -8 -5 -2 -9 -8 -6 -7 -1 -0 -9 -3 -5 -1 -9 -1 -3 -1 -8 -2 -5 -3 -4 -7 -3 -9 -6 -7 -0 -1 -6 -8 -3 -3 -9 -6 -3 -1 -3 -7 -1 -7 -1 -1 -9 -4 -1 -3 -6 -1 -5 -1 -5 -2 -7 -2 -6 -1 -8 -9 -4 -4 -1 -6 -6 -9 -4 -0 -2 -3 -3 -1 -7 -6 -0 -7 -8 -7 -1 -2 -3 -2 -6 -7 -2 -9 -8 -7 -6 -1 -6 -0 -3 -6 -4 -4 -9 -7 -7 -1 -5 -4 -9 -2 -6 -9 -1 -1 -9 -7 -6 -7 -2 -9 -2 -7 -2 -7 -8 -8 -6 -3 -6 -7 -6 -2 -1 -9 -8 -1 -2 -0 -6 -5 -9 -5 -9 -5 -1 -5 -1 -7 -3 -8 -4 -8 -5 -2 -9 -7 -7 -3 -1 -1 -8 -9 -1 -8 -3 -1 -9 -0 -0 -7 -4 -5 -3 -7 -9 -2 -1 -2 -9 -3 -4 -4 -7 -1 -7 -3 -3 -7 -7 -2 -9 -2 -4 -2 -0 -4 -8 -8 -2 -1 -3 -9 -5 -2 -0 -2 -9 -0 -7 -6 -5 -9 -1 -1 -9 -5 -0 -4 -5 -9 -6 -2 -0 -9 -6 -7 -9 -8 -2 -9 -5 -8 -0 -6 -0 -9 -9 -9 -7 -3 -4 -7 -8 -1 -4 -6 -7 -1 -0 -3 -1 -8 -4 -3 -2 -9 -6 -1 -7 -6 -4 -9 -4 -9 -4 -1 -3 -7 -7 -1 -4 -6 -9 -0 -7 -0 -3 -4 -0 -2 -0 -2 -7 -2 -8 -0 -9 -1 -4 -2 -0 -5 -1 -0 -6 -3 -5 -7 -3 -6 -6 -5 -1 -0 -3 -6 -4 -4 -4 -7 -9 -5 -3 -7 -7 -1 -4 -0 -4 -9 -6 -3 -9 -6 -6 -0 -9 -9 -4 -1 -9 -2 -8 -4 -5 -1 -5 -3 -1 -9 -6 -7 -2 -3 -6 -9 -4 -1 -2 -1 -6 -6 -5 -3 -0 -1 -7 -1 -8 -1 -9 -0 -7 -9 -8 -1 -4 -7 -7 -7 -3 -2 -6 -7 -6 -0 -3 -4 -7 -7 -9 -4 -2 -1 -8 -6 -7 -6 -0 -7 -4 -9 -0 -2 -9 -3 -2 -9 -2 -2 -1 -0 -7 -3 -3 -2 -1 -4 -0 -2 -9 -8 -6 -1 -1 -3 -1 -9 -1 -3 -9 -2 -6 -6 -2 -1 -7 -9 -6 -4 -6 -4 -0 -4 -6 -0 -5 -2 -7 -1 -3 -9 -3 -2 -4 -2 -6 -8 -8 -3 -6 -0 -2 -1 -6 -9 -5 -0 -6 -5 -1 -7 -8 -5 -1 -1 -8 -9 -8 -1 -9 -6 -9 -1 -5 -2 -4 -3 -8 -0 -8 -1 -9 -6 -9 -7 -9 -8 -7 -3 -2 -5 -5 -9 -1 -9 -8 -9 -4 -7 -9 -6 -3 -9 -7 -8 -2 -8 -1 -7 -1 -0 -4 -6 -8 -1 -9 -7 -0 -8 -4 -0 -5 -8 -6 -0 -7 -7 -5 -5 -6 -1 -6 -8 -0 -0 -3 -6 -1 -6 -0 -7 -2 -9 -1 -6 -9 -7 -5 -4 -3 -8 -9 -7 -2 -8 -6 -9 -8 -8 -1 -5 -4 -9 -1 -0 -2 -2 -0 -6 -1 -3 -4 -1 -0 -8 -0 -8 -1 -9 -4 -7 -9 -1 -7 -9 -1 -8 -7 -9 -8 -1 -2 -7 -4 -6 -3 -0 -5 -7 -9 -3 -1 -3 -0 -9 -8 -9 -6 -8 -1 -0 -6 -8 -1 -1 -0 -3 -4 -3 -2 -1 -9 -1 -1 -6 -9 -2 -1 -0 -2 -9 -1 -1 -4 -8 -4 -3 -7 -1 -1 -9 -9 -0 -1 -9 -1 -6 -3 -1 -4 -7 -8 -0 -0 -9 -3 -8 -1 -1 -2 -6 -7 -7 -0 -4 -5 -2 -1 -9 -1 -2 -1 -3 -9 -0 -2 -1 -9 -0 -8 -6 -0 -8 -2 -0 -0 -5 -9 -9 -6 -1 -1 -4 -5 -5 -9 -8 -7 -6 -8 -5 -2 -0 -3 -8 -8 -2 -0 -2 -4 -7 -2 -4 -2 -7 -5 -3 -7 -2 -8 -0 -1 -8 -7 -9 -7 -0 -9 -4 -2 -0 -7 -6 -3 -5 -1 -9 -9 -8 -2 -4 -6 -2 -2 -9 -3 -2 -9 -1 -5 -9 -9 -5 -9 -7 -6 -1 -7 -6 -3 -0 -4 -3 -8 -4 -7 -3 -6 -1 -3 -0 -5 -1 -6 -3 -9 -0 -1 -2 -0 -6 -7 -2 -0 -1 -4 -2 -6 -7 -6 -9 -0 -3 -7 -4 -6 -1 -1 -2 -9 -0 -0 -7 -3 -3 -2 -1 -7 -9 -0 -5 -1 -2 -6 -7 -4 -2 -2 -6 -1 -1 -4 -9 -1 -4 -3 -4 -8 -1 -7 -0 -7 -0 -8 -6 -1 -3 -0 -7 -3 -7 -1 -1 -7 -6 -4 -9 -3 -6 -0 -6 -2 -9 -2 -6 -1 -9 -1 -7 -0 -7 -3 -5 -3 -0 -7 -9 -8 -2 -6 -3 -9 -1 -4 -1 -2 -6 -6 -4 -1 -7 -1 -4 -8 -0 -9 -8 -9 -7 -4 -1 -5 -0 -2 -1 -8 -7 -3 -2 -6 -4 -8 -3 -1 -6 -9 -8 -2 -7 -0 -1 -9 -3 -7 -7 -7 -9 -9 -5 -2 -3 -5 -6 -0 -2 -1 -3 -7 -2 -1 -3 -2 -6 -7 -2 -0 -1 -8 -2 -9 -1 -9 -6 -6 -8 -8 -1 -1 -3 -1 -7 -5 -4 -1 -8 -1 -6 -6 -6 -1 -2 -6 -9 -3 -3 -1 -0 -5 -2 -8 -3 -5 -7 -4 -8 -6 -1 -1 -4 -5 -8 -7 -4 -2 -2 -0 -9 -9 -1 -1 -9 -9 -2 -1 -2 -1 -6 -4 -3 -1 -6 -9 -2 -2 -0 -1 -1 -0 -4 -6 -4 -8 -0 -9 -1 -4 -0 -2 -5 -6 -2 -2 -7 -3 -1 -8 -5 -2 -9 -8 -0 -4 -1 -6 -8 -8 -2 -6 -2 -4 -9 -9 -4 -7 -6 -0 -0 -2 -4 -8 -3 -1 -0 -8 -9 -5 -4 -0 -3 -8 -3 -4 -4 -6 -8 -6 -4 -0 -2 -6 -9 -5 -0 -3 -4 -3 -0 -1 -9 -1 -7 -1 -3 -0 -8 -4 -7 -0 -2 -6 -1 -3 -6 -0 -4 -6 -6 -7 -6 -1 -0 -9 -9 -0 -2 -8 -9 -3 -6 -1 -6 -2 -3 -7 -5 -8 -8 -3 -3 -0 -9 -6 -2 -7 -0 -9 -9 -1 -7 -6 -6 -1 -4 -8 -8 -9 -8 -9 -7 -1 -6 -2 -7 -9 -8 -8 -0 -1 -0 -0 -2 -4 -4 -9 -1 -0 -1 -6 -2 -5 -6 -3 -7 -6 -8 -0 -4 -7 -6 -9 -1 -5 -4 -7 -2 -9 -7 -4 -2 -3 -4 -9 -8 -0 -6 -6 -9 -4 -5 -2 -4 -6 -8 -1 -6 -9 -6 -5 -6 -2 -7 -6 -9 -6 -7 -5 -6 -0 -3 -9 -7 -6 -6 -4 -6 -1 -6 -0 -1 -8 -3 -1 -1 -7 -9 -3 -6 -8 -5 -2 -9 -1 -4 -1 -4 -5 -9 -6 -6 -5 -1 -3 -3 -1 -4 -2 -1 -5 -5 -0 -7 -3 -9 -2 -8 -0 -9 -8 -6 -7 -4 -6 -0 -7 -2 -8 -4 -3 -0 -1 -3 -9 -1 -0 -9 -5 -8 -0 -0 -1 -4 -7 -8 -7 -8 -3 -5 -0 -4 -4 -5 -3 -4 -9 -7 -1 -3 -5 -2 -5 -7 -0 -1 -2 -7 -9 -5 -8 -1 -1 -7 -0 -1 -6 -5 -1 -7 -5 -1 -5 -7 -5 -0 -9 -5 -7 -4 -2 -7 -3 -1 -9 -6 -3 -6 -3 -1 -6 -9 -7 -6 -2 -3 -1 -7 -9 -9 -5 -2 -2 -4 -0 -7 -6 -6 -1 -1 -1 -8 -7 -1 -7 -2 -7 -9 -2 -2 -4 -0 -0 -1 -2 -4 -9 -2 -7 -9 -2 -9 -8 -2 -4 -3 -9 -8 -8 -3 -6 -3 -3 -7 -6 -8 -0 -2 -9 -7 -1 -1 -9 -3 -0 -6 -9 -3 -8 -5 -0 -5 -9 -1 -1 -6 -4 -2 -7 -2 -3 -6 -4 -1 -9 -0 -3 -8 -5 -1 -5 -9 -3 -8 -1 -5 -0 -8 -3 -8 -9 -0 -9 -0 -9 -0 -0 -9 -9 -3 -1 -7 -7 -4 -0 -2 -6 -2 -4 -0 -1 -5 -0 -7 -8 -9 -7 -7 -1 -1 -2 -4 -8 -7 -1 -1 -6 -2 -3 -2 -8 -8 -9 -5 -9 -4 -9 -6 -6 -9 -7 -9 -5 -0 -6 -3 -0 -1 -5 -6 -8 -9 -9 -9 -4 -5 -3 -7 -3 -9 -7 -5 -0 -6 -4 -2 -9 -0 -8 -4 -7 -6 -2 -1 -7 -6 -3 -6 -9 -7 -9 -3 -4 -6 -6 -4 -3 -8 -1 -9 -9 -1 -3 -0 -6 -7 -6 -1 -1 -2 -6 -9 -8 -6 -9 -1 -0 -7 -5 -1 -9 -3 -1 -2 -2 -0 -8 -7 -2 -6 -2 -7 -8 -8 -1 -2 -9 -8 -2 -7 -0 -0 -3 -4 -9 -2 -0 -3 -8 -3 -1 -7 -9 -3 -3 -2 -5 -0 -1 -3 -5 -2 -8 -9 -9 -9 -2 -4 -1 -4 -1 -6 -6 -0 -6 -4 -9 -1 -6 -4 -9 -0 -1 -9 -9 -9 -3 -9 -9 -4 -4 -5 -6 -0 -0 -7 -7 -0 -6 -8 -1 -9 -1 -1 -4 -7 -4 -2 -4 -1 -5 -4 -7 -6 -9 -4 -2 -3 -9 -7 -1 -0 -5 -5 -1 -3 -7 -4 -1 -5 -8 -5 -6 -5 -0 -0 -3 -1 -9 -0 -5 -9 -6 -7 -4 -6 -9 -5 -4 -7 -8 -8 -0 -5 -2 -4 -6 -0 -0 -6 -5 -0 -5 -1 -5 -7 -7 -2 -7 -0 -3 -0 -3 -5 -3 -6 -9 -6 -0 -9 -5 -5 -0 -2 -7 -6 -6 -4 -7 -2 -7 -1 -1 -2 -9 -6 -1 -0 -2 -2 -8 -1 -3 -5 -2 -5 -9 -8 -5 -6 -6 -1 -0 -1 -6 -9 -5 -2 -7 -2 -3 -4 -1 -0 -9 -4 -0 -7 -8 -1 -0 -1 -5 -6 -8 -0 -3 -5 -7 -5 -5 -8 -7 -2 -3 -6 -1 -1 -9 -5 -3 -1 -3 -3 -6 -8 -3 -5 -0 -7 -1 -5 -8 -5 -6 -6 -1 -3 -2 -9 -1 -1 -9 -8 -5 -9 -5 -5 -1 -7 -1 -1 -6 -5 -7 -2 -3 -2 -5 -7 -3 -9 -2 -3 -5 -1 -6 -4 -7 -7 -0 -3 -6 -7 -1 -9 -6 -3 -7 -0 -6 -9 -1 -2 -1 -1 -2 -9 -8 -3 -2 -0 -2 -3 -7 -6 -9 -6 -6 -6 -4 -6 -1 -0 -2 -3 -0 -4 -7 -6 -8 -8 -7 -2 -6 -2 -1 -2 -9 -7 -0 -0 -1 -0 -0 -0 -3 -8 -1 -8 -0 -1 -9 -3 -0 -9 -1 -5 -5 -5 -1 -3 -8 -7 -3 -7 -0 -6 -6 -6 -7 -4 -1 -7 -5 -2 -1 -4 -7 -2 -4 -0 -5 -4 -9 -5 -1 -5 -5 -8 -7 -7 -9 -1 -5 -4 -6 -7 -2 -7 -1 -5 -9 -9 -7 -9 -1 -1 -0 -6 -6 -1 -4 -1 -0 -0 -7 -1 -2 -8 -9 -2 -6 -9 -2 -7 -0 -8 -0 -0 -0 -7 -3 -3 -4 -1 -9 -0 -2 -0 -0 -2 -2 -1 -3 -5 -6 -8 -7 -2 -4 -3 -9 -6 -4 -9 -5 -6 -1 -2 -3 -1 -1 -2 -2 -9 -2 -7 -0 -6 -9 -0 -1 -0 -8 -5 -6 -4 -2 -0 -9 -9 -6 -1 -6 -7 -9 -0 -1 -3 -1 -2 -7 -8 -9 -1 -9 -1 -0 -7 -6 -5 -0 -5 -3 -5 -5 -8 -7 -3 -3 -2 -3 -3 -6 -6 -3 -1 -1 -4 -6 -1 -5 -3 -9 -5 -4 -1 -6 -7 -0 -2 -0 -8 -1 -9 -5 -4 -8 -3 -3 -1 -8 -2 -2 -0 -8 -1 -6 -8 -1 -0 -3 -0 -4 -2 -4 -8 -1 -5 -2 -3 -6 -5 -8 -5 -8 -0 -1 -9 -8 -0 -8 -0 -5 -6 -1 -4 -8 -7 -1 -3 -4 -0 -2 -6 -3 -0 -3 -8 -4 -5 -9 -1 -2 -0 -8 -9 -2 -3 -3 -7 -5 -5 -3 -1 -6 -0 -5 -9 -5 -1 -5 -5 -6 -1 -7 -0 -1 -1 -6 -8 -5 -9 -0 -6 -5 -0 -8 -2 -1 -3 -0 -5 -6 -5 -6 -1 -8 -0 -0 -5 -9 -2 -9 -5 -2 -2 -9 -9 -8 -8 -3 -4 -7 -4 -8 -5 -3 -7 -7 -1 -6 -7 -7 -0 -1 -2 -2 -3 -5 -6 -1 -7 -7 -9 -3 -4 -2 -8 -0 -6 -8 -9 -1 -7 -8 -7 -8 -7 -1 -0 -9 -6 -3 -7 -5 -7 -2 -5 -5 -6 -6 -4 -8 -5 -7 -6 -6 -2 -6 -4 -1 -9 -6 -6 -2 -1 -6 -6 -1 -5 -8 -0 -2 -9 -6 -4 -6 -3 -1 -1 -6 -6 -9 -5 -7 -9 -6 -5 -1 -5 -7 -5 -3 -9 -6 -6 -3 -1 -6 -8 -6 -0 -6 -2 -4 -6 -2 -2 -3 -4 -6 -6 -7 -5 -3 -0 -5 -1 -3 -1 -8 -8 -9 -8 -6 -1 -1 -2 -3 -8 -8 -9 -1 -4 -1 -0 -0 -5 -0 -7 -9 -9 -2 -1 -6 -9 -9 -9 -1 -3 -1 -4 -0 -4 -9 -0 -4 -1 -6 -5 -4 -1 -5 -9 -1 -7 -5 -8 -2 -3 -0 -9 -8 -9 -2 -4 -6 -1 -9 -9 -0 -1 -4 -1 -7 -1 -9 -1 -1 -4 -5 -0 -7 -3 -5 -2 -0 -1 -7 -1 -6 -8 -6 -7 -7 -3 -3 -8 -7 -7 -1 -3 -2 -0 -5 -0 -4 -2 -8 -6 -4 -7 -8 -1 -4 -1 -7 -1 -4 -0 -5 -3 -6 -6 -0 -6 -8 -2 -1 -9 -8 -2 -0 -5 -7 -0 -7 -6 -1 -6 -6 -1 -2 -1 -0 -1 -3 -0 -5 -8 -2 -7 -6 -2 -1 -4 -0 -5 -1 -3 -1 -6 -1 -9 -6 -2 -8 -0 -2 -0 -0 -6 -3 -4 -5 -4 -0 -0 -1 -4 -0 -2 -8 -4 -0 -5 -6 -6 -9 -1 -6 -4 -4 -7 -2 -1 -5 -2 -6 -6 -3 -1 -8 -1 -8 -1 -5 -5 -2 -1 -9 -9 -9 -5 -3 -7 -9 -0 -8 -2 -3 -4 -8 -5 -9 -0 -7 -2 -1 -9 -9 -7 -2 -9 -7 -4 -5 -5 -4 -0 -2 -2 -5 -4 -5 -3 -7 -6 -1 -2 -8 -2 -0 -8 -9 -9 -6 -5 -4 -9 -6 -5 -1 -6 -2 -7 -9 -7 -6 -4 -1 -5 -3 -9 -7 -6 -1 -8 -3 -5 -0 -5 -9 -9 -9 -5 -6 -3 -3 -1 -0 -4 -8 -9 -4 -1 -3 -4 -7 -4 -5 -9 -4 -7 -7 -8 -6 -4 -9 -0 -0 -0 -7 -7 -0 -7 -0 -6 -0 -0 -0 -1 -5 -9 -6 -8 -1 -5 -6 -9 -1 -3 -1 -0 -2 -6 -5 -4 -2 -1 -9 -6 -7 -7 -8 -3 -8 -4 -4 -9 -3 -0 -7 -1 -1 -0 -5 -6 -9 -1 -0 -3 -3 -1 -7 -9 -9 -5 -1 -7 -7 -7 -7 -2 -7 -6 -6 -5 -3 -8 -1 -1 -1 -3 -9 -6 -6 -1 -5 -7 -4 -6 -8 -1 -7 -1 -5 -9 -0 -6 -3 -1 -2 -3 -3 -9 -8 -3 -9 -7 -2 -5 -4 -3 -9 -1 -1 -3 -1 -7 -5 -0 -2 -4 -5 -8 -4 -2 -8 -2 -3 -0 -3 -5 -7 -6 -8 -8 -5 -8 -1 -9 -2 -8 -7 -1 -9 -7 -0 -6 -6 -2 -1 -7 -3 -1 -5 -1 -6 -2 -0 -1 -0 -0 -2 -3 -9 -9 -0 -8 -6 -5 -8 -5 -0 -2 -7 -0 -4 -2 -1 -3 -4 -4 -5 -3 -1 -0 -1 -2 -0 -1 -8 -7 -0 -4 -3 -2 -2 -2 -3 -0 -3 -9 -3 -0 -3 -4 -9 -8 -7 -8 -4 -7 -9 -2 -6 -9 -6 -4 -7 -6 -1 -1 -6 -2 -7 -9 -5 -3 -1 -9 -0 -2 -4 -6 -7 -6 -7 -3 -7 -1 -4 -7 -7 -6 -1 -0 -5 -8 -7 -5 -4 -0 -2 -9 -2 -0 -0 -1 -0 -8 -2 -6 -2 -4 -7 -5 -3 -8 -0 -1 -4 -7 -4 -4 -5 -6 -9 -4 -9 -1 -3 -4 -9 -1 -1 -9 -1 -5 -4 -1 -8 -5 -2 -6 -3 -4 -6 -0 -6 -4 -4 -3 -3 -4 -4 -2 -8 -4 -0 -6 -8 -3 -7 -9 -6 -5 -9 -5 -3 -2 -5 -1 -3 -0 -9 -3 -0 -6 -2 -1 -6 -6 -2 -6 -5 -8 -7 -2 -4 -1 -9 -9 -7 -0 -6 -8 -3 -7 -0 -4 -4 -9 -8 -0 -0 -6 -7 -1 -1 -4 -9 -9 -8 -4 -8 -1 -0 -2 -5 -7 -4 -7 -6 -3 -7 -8 -2 -1 -3 -6 -8 -9 -6 -4 -5 -1 -2 -3 -1 -7 -6 -7 -9 -5 -1 -2 -9 -9 -3 -2 -1 -8 -0 -2 -1 -4 -6 -3 -3 -2 -5 -3 -0 -9 -4 -8 -1 -6 -6 -3 -8 -2 -1 -4 -0 -8 -5 -1 -0 -7 -1 -4 -2 -5 -4 -3 -6 -2 -2 -6 -0 -5 -2 -1 -3 -1 -9 -9 -4 -6 -9 -8 -0 -9 -2 -0 -3 -5 -9 -5 -9 -0 -2 -9 -4 -9 -8 -4 -8 -9 -5 -4 -0 -5 -1 -9 -1 -5 -2 -1 -8 -3 -9 -6 -1 -4 -6 -6 -0 -9 -1 -3 -7 -7 -4 -6 -8 -2 -8 -8 -3 -1 -2 -6 -2 -1 -0 -0 -6 -2 -5 -4 -6 -2 -8 -9 -8 -8 -9 -0 -2 -2 -9 -1 -1 -1 -6 -9 -2 -7 -8 -0 -5 -2 -0 -6 -1 -3 -8 -4 -0 -7 -1 -9 -6 -4 -0 -7 -3 -8 -1 -8 -6 -7 -1 -0 -3 -0 -9 -2 -0 -2 -8 -0 -5 -0 -3 -6 -1 -4 -9 -1 -5 -2 -3 -0 -7 -2 -9 -2 -6 -7 -0 -4 -3 -7 -3 -0 -4 -9 -6 -9 -9 -9 -5 -3 -3 -4 -1 -8 -8 -1 -4 -8 -7 -4 -3 -1 -4 -8 -6 -4 -3 -4 -8 -5 -6 -8 -9 -5 -5 -8 -7 -4 -0 -0 -0 -5 -3 -9 -8 -9 -3 -2 -7 -1 -0 -7 -1 -1 -7 -9 -0 -0 -5 -1 -8 -9 -7 -4 -2 -4 -7 -1 -0 -8 -9 -2 -9 -5 -0 -7 -0 -7 -9 -8 -3 -3 -4 -5 -1 -6 -9 -7 -1 -2 -2 -9 -6 -6 -1 -9 -2 -0 -5 -8 -1 -6 -5 -6 -3 -7 -7 -6 -7 -6 -9 -5 -3 -1 -1 -6 -4 -3 -6 -1 -4 -1 -4 -1 -6 -1 -9 -7 -7 -7 -1 -3 -9 -0 -7 -4 -6 -7 -7 -3 -7 -6 -2 -5 -8 -9 -3 -3 -4 -5 -6 -1 -9 -0 -7 -3 -5 -1 -5 -9 -0 -4 -2 -8 -6 -6 -3 -9 -0 -8 -0 -9 -9 -7 -8 -1 -8 -0 -9 -7 -1 -9 -2 -5 -1 -3 -0 -2 -7 -6 -2 -3 -9 -7 -2 -7 -0 -7 -7 -6 -0 -6 -8 -4 -7 -5 -3 -2 -3 -2 -2 -3 -4 -4 -4 -7 -4 -0 -7 -9 -6 -2 -3 -2 -5 -3 -9 -6 -6 -7 -1 -0 -6 -7 -9 -0 -2 -7 -9 -2 -9 -5 -0 -9 -5 -7 -1 -2 -5 -3 -8 -0 -0 -2 -4 -1 -7 -8 -3 -3 -1 -5 -2 -6 -0 -3 -5 -8 -0 -5 -2 -1 -5 -6 -3 -6 -4 -8 -0 -5 -4 -0 -6 -0 -5 -9 -3 -3 -0 -1 -7 -2 -2 -2 -8 -9 -0 -8 -0 -9 -8 -2 -9 -4 -3 -2 -9 -4 -9 -4 -1 -7 -2 -1 -3 -3 -7 -1 -1 -7 -7 -3 -9 -3 -1 -8 -3 -5 -1 -4 -6 -9 -4 -0 -3 -6 -3 -6 -6 -2 -9 -7 -9 -7 -8 -6 -6 -0 -5 -1 -2 -1 -4 -6 -2 -0 -2 -2 -2 -8 -8 -8 -0 -1 -0 -1 -7 -6 -9 -4 -9 -9 -4 -9 -8 -9 -7 -9 -6 -3 -9 -5 -0 -8 -7 -0 -6 -8 -1 -5 -7 -1 -4 -7 -8 -8 -3 -3 -2 -3 -6 -3 -1 -5 -5 -2 -5 -2 -4 -2 -9 -7 -9 -9 -2 -6 -9 -6 -0 -0 -9 -0 -8 -2 -1 -7 -6 -2 -0 -1 -6 -2 -3 -8 -9 -1 -2 -5 -8 -2 -0 -7 -1 -1 -1 -0 -8 -6 -7 -6 -4 -7 -1 -2 -0 -3 -4 -2 -7 -7 -1 -3 -4 -1 -3 -1 -3 -6 -6 -9 -5 -2 -8 -5 -5 -3 -6 -9 -6 -2 -0 -2 -7 -1 -9 -8 -2 -4 -6 -6 -3 -6 -8 -2 -9 -6 -1 -8 -4 -3 -6 -6 -1 -1 -0 -2 -1 -3 -9 -9 -4 -3 -9 -2 -7 -2 -3 -2 -0 -3 -3 -9 -0 -4 -0 -6 -9 -5 -3 -4 -4 -5 -0 -1 -5 -9 -4 -3 -3 -4 -0 -1 -0 -5 -8 -4 -0 -3 -5 -8 -6 -9 -4 -4 -7 -9 -3 -5 -0 -9 -2 -3 -6 -9 -8 -2 -5 -8 -7 -0 -2 -2 -5 -6 -7 -2 -2 -2 -1 -8 -5 -7 -2 -2 -7 -3 -7 -7 -6 -6 -9 -4 -1 -5 -8 -9 -0 -8 -8 -2 -3 -6 -2 -9 -8 -0 -1 -0 -5 -4 -5 -7 -0 -6 -6 -2 -5 -2 -2 -6 -2 -4 -0 -7 -6 -2 -1 -2 -6 -4 -4 -5 -2 -6 -9 -9 -6 -2 -4 -9 -8 -2 -4 -9 -6 -0 -1 -1 -0 -9 -8 -6 -4 -3 -7 -4 -7 -2 -1 -9 -1 -8 -3 -0 -4 -8 -0 -9 -0 -0 -3 -2 -7 -1 -4 -2 -8 -4 -5 -8 -5 -5 -1 -0 -3 -2 -4 -5 -2 -7 -9 -9 -1 -4 -2 -3 -9 -9 -2 -9 -1 -6 -6 -9 -6 -1 -9 -0 -9 -9 -3 -9 -6 -9 -9 -0 -7 -0 -0 -2 -8 -9 -1 -1 -3 -7 -0 -6 -7 -7 -0 -0 -6 -0 -3 -7 -5 -0 -6 -1 -2 -6 -3 -9 -1 -7 -8 -0 -9 -3 -8 -0 -1 -0 -7 -3 -0 -6 -2 -8 -2 -5 -4 -9 -6 -3 -4 -3 -9 -7 -1 -3 -2 -6 -2 -5 -5 -2 -0 -6 -8 -6 -7 -0 -8 -9 -4 -0 -2 -1 -5 -1 -6 -8 -1 -0 -2 -5 -2 -9 -8 -5 -3 -6 -9 -7 -2 -1 -9 -3 -5 -4 -4 -8 -0 -9 -5 -0 -2 -6 -0 -2 -6 -3 -3 -6 -2 -8 -1 -2 -6 -9 -1 -2 -5 -5 -9 -0 -0 -1 -8 -2 -0 -7 -0 -9 -2 -0 -4 -9 -0 -6 -0 -3 -1 -5 -2 -2 -6 -2 -7 -6 -0 -0 -5 -1 -6 -3 -7 -8 -1 -1 -5 -2 -0 -6 -5 -5 -5 -3 -7 -7 -1 -5 -8 -1 -8 -3 -3 -6 -8 -6 -0 -7 -8 -6 -2 -5 -1 -5 -0 -9 -8 -0 -7 -5 -8 -2 -0 -0 -5 -2 -2 -8 -3 -1 -3 -5 -8 -1 -0 -6 -8 -3 -1 -6 -0 -0 -2 -1 -8 -2 -6 -9 -6 -5 -7 -4 -3 -7 -2 -1 -9 -9 -0 -0 -3 -6 -2 -6 -9 -2 -1 -4 -3 -0 -5 -1 -8 -7 -8 -7 -1 -3 -5 -1 -1 -4 -2 -3 -4 -9 -2 -0 -1 -5 -3 -1 -9 -0 -6 -0 -7 -1 -7 -1 -2 -7 -4 -0 -9 -6 -2 -6 -3 -2 -6 -7 -5 -1 -0 -4 -3 -3 -0 -1 -4 -3 -1 -3 -5 -5 -7 -6 -9 -6 -7 -5 -6 -9 -8 -5 -1 -3 -0 -6 -7 -8 -7 -6 -7 -4 -2 -6 -3 -7 -3 -6 -1 -1 -2 -7 -8 -7 -9 -4 -1 -9 -8 -7 -3 -8 -8 -5 -0 -2 -7 -8 -9 -9 -7 -7 -2 -3 -1 -9 -8 -6 -9 -0 -4 -6 -1 -5 -3 -3 -3 -0 -1 -8 -1 -4 -6 -8 -7 -6 -8 -0 -5 -3 -4 -6 -3 -0 -2 -9 -4 -9 -1 -5 -1 -0 -7 -4 -4 -1 -8 -4 -5 -5 -9 -9 -2 -2 -2 -4 -4 -9 -6 -2 -5 -2 -2 -0 -2 -7 -9 -5 -0 -7 -0 -8 -0 -1 -7 -8 -2 -9 -4 -0 -8 -9 -4 -5 -3 -5 -0 -3 -3 -8 -0 -7 -0 -6 -7 -2 -0 -3 -6 -2 -1 -8 -6 -0 -1 -3 -8 -0 -3 -6 -3 -9 -1 -1 -2 -6 -8 -8 -9 -4 -9 -5 -9 -9 -6 -6 -4 -9 -0 -4 -0 -1 -3 -0 -0 -1 -9 -7 -2 -1 -6 -7 -2 -2 -1 -8 -1 -8 -9 -6 -2 -9 -9 -7 -4 -0 -9 -6 -8 -9 -9 -9 -7 -9 -5 -4 -7 -0 -9 -6 -4 -9 -4 -0 -7 -7 -9 -0 -0 -5 -6 -7 -2 -1 -3 -3 -8 -0 -1 -3 -8 -4 -3 -1 -2 -9 -9 -4 -5 -1 -4 -0 -3 -8 -8 -7 -1 -1 -6 -8 -2 -8 -6 -3 -9 -5 -9 -7 -2 -3 -1 -2 -0 -6 -3 -1 -9 -5 -2 -7 -3 -0 -1 -1 -9 -5 -2 -2 -6 -0 -6 -5 -8 -4 -3 -3 -0 -2 -9 -5 -7 -4 -7 -2 -5 -9 -5 -4 -7 -8 -2 -3 -2 -3 -6 -9 -2 -6 -3 -4 -1 -6 -1 -9 -0 -0 -6 -2 -9 -0 -9 -7 -8 -0 -8 -6 -2 -3 -5 -0 -5 -4 -2 -6 -0 -9 -8 -5 -9 -6 -1 -9 -3 -7 -1 -3 -7 -4 -1 -1 -9 -6 -9 -5 -8 -0 -2 -5 -3 -8 -0 -1 -4 -1 -6 -6 -9 -5 -8 -0 -7 -3 -4 -9 -2 -9 -9 -3 -1 -0 -8 -5 -3 -2 -4 -5 -2 -1 -3 -9 -8 -4 -4 -7 -9 -3 -7 -0 -7 -7 -9 -9 -8 -7 -1 -2 -0 -0 -0 -7 -6 -6 -8 -0 -1 -3 -0 -2 -6 -3 -6 -8 -0 -5 -6 -2 -0 -2 -9 -5 -0 -2 -4 -3 -9 -9 -1 -9 -5 -4 -4 -2 -0 -1 -7 -6 -6 -7 -0 -6 -4 -9 -8 -8 -9 -3 -3 -1 -0 -4 -4 -7 -0 -5 -7 -6 -7 -8 -1 -3 -4 -6 -7 -0 -4 -3 -2 -6 -3 -7 -3 -7 -1 -9 -1 -3 -9 -0 -1 -7 -9 -8 -4 -3 -5 -4 -0 -7 -2 -2 -6 -9 -5 -3 -9 -9 -8 -1 -6 -1 -7 -8 -3 -1 -1 -2 -8 -4 -5 -6 -1 -7 -0 -0 -1 -8 -7 -4 -9 -9 -7 -0 -5 -1 -5 -8 -6 -8 -5 -6 -2 -6 -1 -1 -9 -6 -4 -3 -5 -1 -8 -5 -7 -9 -7 -2 -7 -1 -5 -9 -1 -3 -9 -5 -0 -4 -6 -3 -5 -3 -3 -6 -1 -0 -2 -3 -2 -2 -6 -2 -0 -1 -2 -7 -8 -5 -6 -2 -8 -4 -6 -8 -5 -8 -6 -9 -8 -7 -1 -6 -7 -3 -7 -7 -4 -0 -1 -3 -9 -2 -0 -0 -5 -4 -7 -1 -6 -9 -7 -8 -4 -3 -3 -1 -3 -1 -5 -6 -0 -3 -5 -0 -8 -7 -7 -8 -6 -3 -6 -9 -5 -9 -2 -1 -2 -3 -5 -2 -2 -1 -1 -3 -3 -5 -8 -7 -9 -3 -4 -2 -7 -1 -7 -8 -2 -2 -3 -9 -5 -5 -7 -7 -3 -9 -0 -5 -9 -6 -6 -9 -2 -6 -3 -9 -2 -0 -7 -0 -7 -7 -1 -2 -0 -3 -2 -9 -0 -3 -3 -6 -3 -0 -5 -2 -6 -6 -7 -8 -0 -1 -5 -7 -1 -2 -9 -2 -5 -3 -6 -3 -6 -1 -0 -4 -5 -1 -9 -4 -6 -0 -5 -8 -4 -0 -4 -5 -3 -1 -5 -1 -5 -5 -2 -1 -0 -9 -6 -7 -5 -9 -9 -3 -4 -7 -7 -5 -6 -3 -2 -0 -4 -4 -0 -8 -5 -9 -1 -5 -5 -5 -7 -8 -1 -0 -7 -0 -4 -4 -1 -5 -6 -4 -2 -8 -2 -6 -8 -1 -2 -3 -8 -9 -1 -3 -9 -9 -6 -7 -1 -2 -7 -7 -3 -3 -1 -1 -9 -7 -2 -1 -8 -9 -2 -7 -8 -4 -0 -4 -3 -5 -8 -9 -3 -3 -2 -9 -0 -7 -7 -1 -9 -0 -4 -2 -2 -8 -9 -4 -3 -9 -4 -6 -3 -6 -0 -5 -1 -3 -0 -1 -2 -5 -0 -7 -1 -7 -2 -7 -8 -7 -4 -9 -1 -5 -0 -8 -2 -9 -2 -1 -0 -1 -2 -6 -9 -2 -5 -3 -5 -3 -4 -9 -1 -4 -7 -1 -8 -1 -8 -8 -9 -4 -6 -1 -9 -9 -3 -4 -1 -2 -4 -3 -5 -9 -0 -7 -2 -8 -2 -9 -9 -9 -9 -0 -7 -1 -2 -3 -3 -1 -9 -9 -8 -8 -3 -5 -1 -2 -1 -7 -2 -0 -7 -2 -1 -1 -7 -0 -6 -4 -0 -8 -1 -8 -7 -2 -4 -7 -3 -0 -9 -6 -7 -5 -9 -7 -4 -5 -2 -9 -6 -7 -1 -3 -7 -0 -3 -1 -4 -7 -5 -2 -0 -4 -4 -9 -7 -4 -9 -0 -1 -0 -2 -1 -6 -6 -3 -6 -4 -9 -2 -2 -3 -1 -1 -0 -7 -1 -2 -7 -9 -0 -9 -0 -6 -7 -1 -0 -9 -7 -5 -0 -8 -4 -8 -5 -0 -0 -0 -3 -6 -5 -0 -8 -2 -7 -6 -0 -8 -5 -0 -2 -6 -9 -4 -2 -0 -9 -3 -8 -1 -3 -6 -7 -6 -7 -0 -3 -1 -9 -2 -1 -9 -7 -3 -0 -6 -4 -2 -2 -5 -3 -7 -8 -8 -5 -7 -4 -2 -7 -4 -9 -0 -5 -9 -9 -9 -2 -8 -8 -8 -0 -3 -1 -1 -1 -0 -9 -0 -4 -1 -7 -4 -7 -6 -1 -1 -4 -3 -7 -1 -4 -6 -9 -5 -8 -9 -3 -2 -9 -1 -5 -3 -9 -6 -3 -6 -7 -9 -1 -7 -3 -2 -5 -6 -9 -7 -2 -6 -2 -8 -6 -5 -7 -7 -3 -5 -9 -0 -0 -4 -2 -2 -5 -1 -9 -5 -9 -6 -8 -0 -8 -5 -3 -7 -6 -1 -9 -3 -5 -8 -0 -9 -4 -0 -7 -5 -6 -1 -4 -6 -5 -0 -4 -9 -7 -1 -9 -6 -6 -6 -1 -4 -8 -1 -7 -2 -4 -9 -7 -5 -0 -0 -0 -8 -0 -7 -7 -0 -2 -6 -9 -0 -9 -8 -7 -2 -9 -7 -3 -9 -3 -9 -9 -0 -7 -5 -2 -4 -5 -8 -7 -8 -9 -1 -2 -2 -7 -7 -4 -7 -0 -6 -5 -9 -7 -2 -0 -0 -1 -2 -9 -1 -3 -4 -0 -6 -4 -9 -5 -3 -0 -2 -0 -1 -6 -5 -8 -0 -5 -7 -6 -4 -7 -0 -2 -4 -2 -1 -9 -3 -9 -0 -1 -0 -5 -7 -6 -5 -0 -5 -6 -1 -0 -0 -0 -9 -0 -3 -1 -7 -3 -7 -9 -8 -4 -4 -8 -3 -3 -0 -6 -4 -1 -0 -0 -2 -2 -2 -1 -1 -7 -3 -7 -6 -8 -6 -3 -4 -6 -4 -9 -3 -3 -9 -2 -0 -1 -3 -2 -5 -1 -2 -4 -0 -3 -6 -2 -2 -1 -6 -9 -0 -6 -1 -2 -4 -1 -3 -9 -7 -6 -0 -4 -5 -3 -3 -7 -2 -3 -4 -4 -8 -4 -6 -2 -1 -7 -0 -5 -8 -1 -2 -8 -3 -5 -1 -6 -9 -0 -9 -4 -9 -1 -0 -7 -0 -9 -3 -7 -5 -6 -9 -9 -9 -6 -4 -8 -9 -7 -9 -7 -5 -7 -1 -2 -6 -7 -6 -0 -9 -7 -5 -9 -7 -1 -2 -6 -0 -5 -6 -6 -1 -0 -0 -0 -4 -9 -8 -9 -6 -8 -0 -2 -8 -4 -9 -7 -4 -1 -1 -7 -6 -1 -5 -7 -6 -2 -2 -3 -0 -7 -9 -0 -7 -2 -6 -0 -3 -6 -1 -2 -3 -3 -1 -9 -0 -5 -6 -2 -3 -6 -1 -4 -0 -0 -4 -6 -9 -8 -7 -4 -8 -4 -3 -9 -7 -8 -9 -8 -3 -6 -7 -3 -0 -1 -2 -3 -8 -2 -0 -8 -0 -5 -4 -2 -9 -9 -4 -0 -7 -3 -2 -2 -9 -4 -5 -1 -0 -5 -9 -6 -1 -5 -0 -7 -6 -4 -2 -5 -3 -7 -9 -3 -9 -1 -8 -1 -6 -8 -3 -4 -9 -0 -9 -1 -9 -4 -9 -6 -2 -6 -0 -0 -6 -0 -8 -7 -8 -9 -9 -0 -7 -7 -4 -2 -6 -0 -2 -6 -9 -5 -2 -1 -1 -1 -0 -1 -0 -8 -0 -6 -6 -4 -2 -8 -1 -9 -3 -9 -7 -1 -5 -4 -6 -2 -1 -7 -6 -8 -0 -7 -7 -0 -7 -2 -6 -9 -3 -6 -7 -6 -5 -9 -2 -9 -4 -4 -1 -0 -1 -4 -5 -4 -4 -6 -8 -5 -2 -3 -6 -2 -8 -5 -3 -3 -0 -2 -3 -3 -3 -9 -0 -3 -0 -3 -0 -3 -2 -9 -7 -5 -4 -9 -2 -4 -0 -1 -0 -6 -5 -0 -2 -8 -1 -3 -5 -5 -8 -9 -2 -7 -1 -6 -6 -6 -1 -4 -0 -4 -9 -6 -1 -8 -0 -9 -4 -5 -1 -6 -1 -1 -0 -9 -5 -9 -7 -9 -1 -6 -0 -0 -1 -7 -5 -8 -9 -7 -9 -9 -4 -6 -7 -7 -3 -6 -8 -0 -2 -0 -9 -1 -6 -6 -9 -6 -1 -8 -8 -1 -2 -8 -6 -1 -9 -7 -5 -2 -6 -0 -1 -7 -7 -5 -7 -3 -1 -6 -1 -0 -2 -5 -4 -2 -7 -3 -7 -3 -6 -4 -9 -5 -3 -1 -4 -6 -3 -9 -7 -8 -1 -9 -3 -1 -0 -5 -8 -5 -7 -8 -4 -1 -5 -4 -7 -5 -8 -3 -2 -1 -9 -2 -2 -5 -6 -1 -4 -8 -1 -1 -8 -1 -4 -9 -8 -3 -6 -8 -1 -5 -3 -7 -2 -4 -2 -5 -0 -4 -2 -1 -8 -4 -5 -4 -1 -6 -5 -5 -8 -2 -2 -9 -0 -7 -3 -8 -2 -8 -1 -4 -7 -4 -6 -7 -4 -4 -1 -5 -7 -9 -2 -6 -1 -0 -7 -1 -0 -9 -3 -7 -6 -7 -2 -1 -6 -7 -4 -9 -1 -7 -8 -5 -6 -7 -6 -6 -9 -7 -3 -9 -6 -0 -0 -6 -9 -2 -1 -4 -6 -3 -0 -9 -9 -6 -4 -7 -6 -0 -2 -9 -0 -1 -1 -0 -5 -9 -1 -1 -9 -2 -2 -4 -1 -0 -8 -3 -1 -5 -7 -2 -9 -8 -8 -0 -7 -9 -9 -2 -4 -1 -6 -9 -4 -4 -3 -6 -1 -3 -2 -3 -7 -5 -4 -3 -4 -2 -0 -7 -1 -6 -8 -1 -2 -1 -3 -0 -1 -0 -9 -9 -4 -5 -5 -2 -1 -8 -3 -8 -7 -8 -4 -2 -0 -6 -4 -5 -3 -2 -8 -0 -2 -7 -5 -7 -8 -5 -7 -6 -6 -3 -8 -5 -7 -1 -9 -6 -0 -5 -0 -7 -7 -9 -7 -8 -5 -5 -2 -1 -8 -9 -1 -7 -3 -5 -0 -0 -9 -6 -2 -6 -6 -2 -4 -9 -8 -6 -6 -2 -5 -8 -9 -5 -6 -2 -7 -1 -7 -8 -5 -3 -1 -3 -5 -9 -6 -4 -9 -1 -8 -0 -8 -6 -7 -9 -7 -2 -1 -7 -6 -3 -1 -7 -4 -0 -8 -3 -9 -1 -2 -9 -5 -1 -0 -7 -6 -7 -8 -4 -5 -3 -0 -8 -2 -8 -0 -5 -0 -5 -0 -1 -9 -2 -3 -7 -3 -9 -9 -3 -9 -1 -0 -2 -9 -3 -3 -2 -6 -6 -8 -7 -7 -0 -9 -1 -7 -3 -3 -7 -5 -5 -0 -4 -9 -8 -2 -1 -9 -3 -3 -4 -2 -4 -3 -9 -1 -4 -0 -2 -7 -5 -3 -1 -6 -1 -5 -4 -8 -7 -4 -2 -5 -1 -7 -9 -8 -0 -5 -7 -4 -8 -2 -5 -9 -3 -4 -5 -6 -7 -5 -9 -8 -3 -7 -7 -3 -2 -8 -8 -2 -0 -1 -2 -0 -4 -1 -9 -0 -1 -4 -3 -1 -9 -4 -4 -5 -4 -5 -8 -0 -5 -0 -0 -9 -3 -2 -5 -9 -7 -4 -8 -7 -8 -0 -9 -6 -3 -3 -0 -7 -6 -6 -8 -8 -2 -1 -4 -9 -6 -4 -7 -5 -0 -4 -2 -9 -8 -8 -6 -6 -8 -3 -2 -0 -9 -1 -5 -3 -1 -0 -4 -9 -5 -9 -6 -3 -0 -9 -6 -7 -2 -7 -3 -0 -3 -3 -1 -8 -7 -2 -8 -7 -1 -0 -0 -6 -2 -0 -1 -0 -5 -9 -2 -5 -9 -9 -4 -0 -4 -0 -8 -4 -3 -1 -6 -4 -4 -1 -0 -9 -8 -8 -1 -1 -9 -8 -6 -4 -1 -8 -8 -1 -5 -1 -6 -3 -3 -5 -5 -4 -1 -2 -3 -6 -9 -8 -6 -1 -3 -4 -7 -9 -1 -5 -7 -3 -0 -6 -3 -4 -8 -8 -8 -6 -1 -0 -8 -8 -3 -2 -1 -6 -9 -8 -9 -0 -9 -1 -5 -9 -2 -6 -2 -2 -2 -5 -1 -9 -4 -0 -1 -1 -3 -4 -0 -6 -9 -8 -1 -7 -6 -4 -0 -6 -3 -0 -2 -5 -1 -5 -4 -4 -7 -1 -1 -0 -7 -7 -0 -4 -9 -7 -6 -5 -9 -1 -9 -6 -7 -9 -9 -2 -1 -2 -6 -0 -5 -1 -3 -1 -7 -2 -3 -5 -4 -1 -9 -3 -6 -0 -3 -3 -5 -0 -4 -8 -0 -3 -6 -0 -1 -9 -3 -1 -1 -0 -4 -5 -2 -2 -1 -6 -7 -6 -1 -9 -7 -9 -7 -3 -9 -2 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c5fff6c --- /dev/null +++ b/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + + javacnn + javacnn + 0.5-SNAPSHOT + + Implementation of a CNN in Java + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + -deprecation + UTF-8 + + + + + + + + diff --git a/readme-cn.md b/readme-cn.md deleted file mode 100644 index 49fb496..0000000 --- a/readme-cn.md +++ /dev/null @@ -1,25 +0,0 @@ -# JavaCNN -一个卷积神经网络的java实现. 仿Matlab toolbox(https://github.com/rasmusbergpalm/DeepLearnToolbox )实现的,同时进行了部分改进,使得卷积核和采样块可以为矩形而不仅仅是正方形。更多细节,请查看http://www.cnblogs.com/fengfenggirl/p/cnn_implement.html -## 创建一个卷积神经网络 - - LayerBuilder builder = new LayerBuilder(); - builder.addLayer(Layer.buildInputLayer(new Size(28, 28))); - builder.addLayer(Layer.buildConvLayer(6, new Size(5, 5))); - builder.addLayer(Layer.buildSampLayer(new Size(2, 2))); - builder.addLayer(Layer.buildConvLayer(12, new Size(5, 5))); - builder.addLayer(Layer.buildSampLayer(new Size(2, 2))); - builder.addLayer(Layer.buildOutputLayer(10)); - CNN cnn = new CNN(builder, 50); - -## 在 MNIST 数据集上测试 - - String fileName = "data/train.format"; - Dataset dataset = Dataset.load(fileName, ",", 784); - cnn.train(dataset, 100); - Dataset testset = Dataset.load("data/test.format", ",", -1); - cnn.predict(testset, "data/test.predict"); - -迭代100次,四核CPU大约需要运行一个小时后,正确率97.8% - -##Lisence - MIT \ No newline at end of file diff --git a/readme.md b/readme.md index 329ada9..6520b53 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,40 @@ # JavaCNN -A Java implement of Convolutional Neural Network. Learn from DeepLearnToolbox(https://github.com/rasmusbergpalm/DeepLearnToolbox) more detail. see here(http://www.cnblogs.com/fengfenggirl/p/cnn_implement.html) + +A Java implementation of Convolutional Neural Network. +This is a mavenized fork of https://github.com/BigPeng/JavaCNN refactored for the intention to use it in productive environments. + +Original ideas are take from the DeepLearnToolbox (https://github.com/rasmusbergpalm/DeepLearnToolbox). + + +## Include in your project + +If you use maven, it's simple: Just add the dependency + + + + + javacnn + javacnn + 0.4 + + + + +and ratopi's repository + + + + ratopi.de releases + http://ratopi.github.io/maven/releases/ + + false + + + + +to your project's pom.xml. + + ## Build a CNN LayerBuilder builder = new LayerBuilder(); @@ -10,16 +45,20 @@ A Java implement of Convolutional Neural Network. Learn from DeepLearnToolbox(ht builder.addLayer(Layer.buildSampLayer(new Size(2, 2))); builder.addLayer(Layer.buildOutputLayer(10)); CNN cnn = new CNN(builder, 50); - + + ## Run on MNIST dataset - - String fileName = "data/train.format"; - Dataset dataset = Dataset.load(fileName, ",", 784); - cnn.train(dataset, 100); - Dataset testset = Dataset.load("data/test.format", ",", -1); - cnn.predict(testset, "data/test.predict"); -It takes a about an hour to complete 100 iteration and get a precison of 97.8% +For running on MNIST dataset see project https://github.com/ratopi/javacnn.mnist. + + +## Source Code + +Get the source code from github: + + git clone https://github.com/ratopi/JavaCNN.git + + +## License -##Lisence - MIT \ No newline at end of file +MIT diff --git a/src/edu/hitsz/c102c/cnn/CNN.java b/src/edu/hitsz/c102c/cnn/CNN.java deleted file mode 100644 index 096ba73..0000000 --- a/src/edu/hitsz/c102c/cnn/CNN.java +++ /dev/null @@ -1,737 +0,0 @@ -package edu.hitsz.c102c.cnn; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.PrintWriter; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import edu.hitsz.c102c.cnn.Layer.Size; -import edu.hitsz.c102c.dataset.Dataset; -import edu.hitsz.c102c.dataset.Dataset.Record; -import edu.hitsz.c102c.util.ConcurenceRunner.TaskManager; -import edu.hitsz.c102c.util.Log; -import edu.hitsz.c102c.util.Util; -import edu.hitsz.c102c.util.Util.Operator; - -public class CNN implements Serializable { - /** - * - */ - private static final long serialVersionUID = 337920299147929932L; - private static double ALPHA = 0.85; - protected static final double LAMBDA = 0; - // ����ĸ��� - private List layers; - // ���� - private int layerNum; - - // �������µĴ�С - private int batchSize; - // �������������Ծ����ÿһ��Ԫ�س���һ��ֵ - private Operator divide_batchSize; - - // �������������Ծ����ÿһ��Ԫ�س���alphaֵ - private Operator multiply_alpha; - - // �������������Ծ����ÿһ��Ԫ�س���1-labmda*alphaֵ - private Operator multiply_lambda; - - /** - * ��ʼ������ - * - * @param layerBuilder - * ����� - * @param inputMapSize - * ����map�Ĵ�С - * @param classNum - * ���ĸ�����Ҫ�����ݼ������ת��Ϊ0-classNum-1����ֵ - */ - public CNN(LayerBuilder layerBuilder, final int batchSize) { - layers = layerBuilder.mLayers; - layerNum = layers.size(); - this.batchSize = batchSize; - setup(batchSize); - initPerator(); - } - - /** - * ��ʼ�������� - */ - private void initPerator() { - divide_batchSize = new Operator() { - - private static final long serialVersionUID = 7424011281732651055L; - - @Override - public double process(double value) { - return value / batchSize; - } - - }; - multiply_alpha = new Operator() { - - private static final long serialVersionUID = 5761368499808006552L; - - @Override - public double process(double value) { - - return value * ALPHA; - } - - }; - multiply_lambda = new Operator() { - - private static final long serialVersionUID = 4499087728362870577L; - - @Override - public double process(double value) { - - return value * (1 - LAMBDA * ALPHA); - } - - }; - } - - /** - * ��ѵ������ѵ������ - * - * @param trainset - * @param repeat - * �����Ĵ��� - */ - public void train(Dataset trainset, int repeat) { - // ����ֹͣ��ť - new Lisenter().start(); - for (int t = 0; t < repeat && !stopTrain.get(); t++) { - int epochsNum = trainset.size() / batchSize; - if (trainset.size() % batchSize != 0) - epochsNum++;// ���ȡһ�Σ�������ȡ�� - Log.i(""); - Log.i(t + "th iter epochsNum:" + epochsNum); - int right = 0; - int count = 0; - for (int i = 0; i < epochsNum; i++) { - int[] randPerm = Util.randomPerm(trainset.size(), batchSize); - Layer.prepareForNewBatch(); - - for (int index : randPerm) { - boolean isRight = train(trainset.getRecord(index)); - if (isRight) - right++; - count++; - Layer.prepareForNewRecord(); - } - - // ����һ��batch�����Ȩ�� - updateParas(); - if (i % 50 == 0) { - System.out.print(".."); - if (i + 50 > epochsNum) - System.out.println(); - } - } - double p = 1.0 * right / count; - if (t % 10 == 1 && p > 0.96) {//��̬����׼ѧϰ���� - ALPHA = 0.001 + ALPHA * 0.9; - Log.i("Set alpha = " + ALPHA); - } - Log.i("precision " + right + "/" + count + "=" + p); - } - } - - private static AtomicBoolean stopTrain; - - static class Lisenter extends Thread { - Lisenter() { - setDaemon(true); - stopTrain = new AtomicBoolean(false); - } - - @Override - public void run() { - System.out.println("Input & to stop train."); - while (true) { - try { - int a = System.in.read(); - if (a == '&') { - stopTrain.compareAndSet(false, true); - break; - } - } catch (IOException e) { - e.printStackTrace(); - } - } - System.out.println("Lisenter stop"); - } - - } - - /** - * �������� - * - * @param trainset - * @return - */ - public double test(Dataset trainset) { - Layer.prepareForNewBatch(); - Iterator iter = trainset.iter(); - int right = 0; - while (iter.hasNext()) { - Record record = iter.next(); - forward(record); - Layer outputLayer = layers.get(layerNum - 1); - int mapNum = outputLayer.getOutMapNum(); - double[] out = new double[mapNum]; - for (int m = 0; m < mapNum; m++) { - double[][] outmap = outputLayer.getMap(m); - out[m] = outmap[0][0]; - } - if (record.getLable().intValue() == Util.getMaxIndex(out)) - right++; - } - double p = 1.0 * right / trainset.size(); - Log.i("precision", p + ""); - return p; - } - - /** - * Ԥ���� - * - * @param testset - * @param fileName - */ - public void predict(Dataset testset, String fileName) { - Log.i("begin predict"); - try { - int max = layers.get(layerNum - 1).getClassNum(); - PrintWriter writer = new PrintWriter(new File(fileName)); - Layer.prepareForNewBatch(); - Iterator iter = testset.iter(); - while (iter.hasNext()) { - Record record = iter.next(); - forward(record); - Layer outputLayer = layers.get(layerNum - 1); - - int mapNum = outputLayer.getOutMapNum(); - double[] out = new double[mapNum]; - for (int m = 0; m < mapNum; m++) { - double[][] outmap = outputLayer.getMap(m); - out[m] = outmap[0][0]; - } - // int lable = - // Util.binaryArray2int(out); - int lable = Util.getMaxIndex(out); - // if (lable >= max) - // lable = lable - (1 << (out.length - - // 1)); - writer.write(lable + "\n"); - } - writer.flush(); - writer.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - Log.i("end predict"); - } - - private boolean isSame(double[] output, double[] target) { - boolean r = true; - for (int i = 0; i < output.length; i++) - if (Math.abs(output[i] - target[i]) > 0.5) { - r = false; - break; - } - - return r; - } - - /** - * ѵ��һ����¼��ͬʱ�����Ƿ�Ԥ����ȷ��ǰ��¼ - * - * @param record - * @return - */ - private boolean train(Record record) { - forward(record); - boolean result = backPropagation(record); - return result; - // System.exit(0); - } - - /* - * ������ - */ - private boolean backPropagation(Record record) { - boolean result = setOutLayerErrors(record); - setHiddenLayerErrors(); - return result; - } - - /** - * ���²��� - */ - private void updateParas() { - for (int l = 1; l < layerNum; l++) { - Layer layer = layers.get(l); - Layer lastLayer = layers.get(l - 1); - switch (layer.getType()) { - case conv: - case output: - updateKernels(layer, lastLayer); - updateBias(layer, lastLayer); - break; - default: - break; - } - } - } - - /** - * ����ƫ�� - * - * @param layer - * @param lastLayer - */ - private void updateBias(final Layer layer, Layer lastLayer) { - final double[][][][] errors = layer.getErrors(); - int mapNum = layer.getOutMapNum(); - - new TaskManager(mapNum) { - - @Override - public void process(int start, int end) { - for (int j = start; j < end; j++) { - double[][] error = Util.sum(errors, j); - // ����ƫ�� - double deltaBias = Util.sum(error) / batchSize; - double bias = layer.getBias(j) + ALPHA * deltaBias; - layer.setBias(j, bias); - } - } - }.start(); - - } - - /** - * ����layer��ľ����ˣ�Ȩ�أ���ƫ�� - * - * @param layer - * ��ǰ�� - * @param lastLayer - * ǰһ�� - */ - private void updateKernels(final Layer layer, final Layer lastLayer) { - int mapNum = layer.getOutMapNum(); - final int lastMapNum = lastLayer.getOutMapNum(); - new TaskManager(mapNum) { - - @Override - public void process(int start, int end) { - for (int j = start; j < end; j++) { - for (int i = 0; i < lastMapNum; i++) { - // ��batch��ÿ����¼delta��� - double[][] deltaKernel = null; - for (int r = 0; r < batchSize; r++) { - double[][] error = layer.getError(r, j); - if (deltaKernel == null) - deltaKernel = Util.convnValid( - lastLayer.getMap(r, i), error); - else {// �ۻ���� - deltaKernel = Util.matrixOp(Util.convnValid( - lastLayer.getMap(r, i), error), - deltaKernel, null, null, Util.plus); - } - } - - // ����batchSize - deltaKernel = Util.matrixOp(deltaKernel, - divide_batchSize); - // ���¾����� - double[][] kernel = layer.getKernel(i, j); - deltaKernel = Util.matrixOp(kernel, deltaKernel, - multiply_lambda, multiply_alpha, Util.plus); - layer.setKernel(i, j, deltaKernel); - } - } - - } - }.start(); - - } - - /** - * �����н�����IJв� - */ - private void setHiddenLayerErrors() { - for (int l = layerNum - 2; l > 0; l--) { - Layer layer = layers.get(l); - Layer nextLayer = layers.get(l + 1); - switch (layer.getType()) { - case samp: - setSampErrors(layer, nextLayer); - break; - case conv: - setConvErrors(layer, nextLayer); - break; - default:// ֻ�в�����;�������Ҫ�����в�����û�вв������Ѿ������� - break; - } - } - } - - /** - * ���ò�����IJв� - * - * @param layer - * @param nextLayer - */ - private void setSampErrors(final Layer layer, final Layer nextLayer) { - int mapNum = layer.getOutMapNum(); - final int nextMapNum = nextLayer.getOutMapNum(); - new TaskManager(mapNum) { - - @Override - public void process(int start, int end) { - for (int i = start; i < end; i++) { - double[][] sum = null;// ��ÿһ������������� - for (int j = 0; j < nextMapNum; j++) { - double[][] nextError = nextLayer.getError(j); - double[][] kernel = nextLayer.getKernel(i, j); - // �Ծ����˽���180����ת��Ȼ�����fullģʽ�µþ��� - if (sum == null) - sum = Util - .convnFull(nextError, Util.rot180(kernel)); - else - sum = Util.matrixOp( - Util.convnFull(nextError, - Util.rot180(kernel)), sum, null, - null, Util.plus); - } - layer.setError(i, sum); - } - } - - }.start(); - - } - - /** - * ���þ�����IJв� - * - * @param layer - * @param nextLayer - */ - private void setConvErrors(final Layer layer, final Layer nextLayer) { - // ���������һ��Ϊ�����㣬�������map������ͬ����һ��mapֻ����һ���һ��map���ӣ� - // ���ֻ�轫��һ��IJв�kronecker��չ���õ������ - int mapNum = layer.getOutMapNum(); - new TaskManager(mapNum) { - - @Override - public void process(int start, int end) { - for (int m = start; m < end; m++) { - Size scale = nextLayer.getScaleSize(); - double[][] nextError = nextLayer.getError(m); - double[][] map = layer.getMap(m); - // ������ˣ����Եڶ��������ÿ��Ԫ��value����1-value���� - double[][] outMatrix = Util.matrixOp(map, - Util.cloneMatrix(map), null, Util.one_value, - Util.multiply); - outMatrix = Util.matrixOp(outMatrix, - Util.kronecker(nextError, scale), null, null, - Util.multiply); - layer.setError(m, outMatrix); - } - - } - - }.start(); - - } - - /** - * ���������IJв�ֵ,�������񾭵�Ԫ�������٣��ݲ����Ƕ��߳� - * - * @param record - * @return - */ - private boolean setOutLayerErrors(Record record) { - - Layer outputLayer = layers.get(layerNum - 1); - int mapNum = outputLayer.getOutMapNum(); - // double[] target = - // record.getDoubleEncodeTarget(mapNum); - // double[] outmaps = new double[mapNum]; - // for (int m = 0; m < mapNum; m++) { - // double[][] outmap = outputLayer.getMap(m); - // double output = outmap[0][0]; - // outmaps[m] = output; - // double errors = output * (1 - output) * - // (target[m] - output); - // outputLayer.setError(m, 0, 0, errors); - // } - // // ��ȷ - // if (isSame(outmaps, target)) - // return true; - // return false; - - double[] target = new double[mapNum]; - double[] outmaps = new double[mapNum]; - for (int m = 0; m < mapNum; m++) { - double[][] outmap = outputLayer.getMap(m); - outmaps[m] = outmap[0][0]; - - } - int lable = record.getLable().intValue(); - target[lable] = 1; - // Log.i(record.getLable() + "outmaps:" + - // Util.fomart(outmaps) - // + Arrays.toString(target)); - for (int m = 0; m < mapNum; m++) { - outputLayer.setError(m, 0, 0, outmaps[m] * (1 - outmaps[m]) - * (target[m] - outmaps[m])); - } - return lable == Util.getMaxIndex(outmaps); - } - - /** - * ǰ�����һ����¼ - * - * @param record - */ - private void forward(Record record) { - // ����������map - setInLayerOutput(record); - for (int l = 1; l < layers.size(); l++) { - Layer layer = layers.get(l); - Layer lastLayer = layers.get(l - 1); - switch (layer.getType()) { - case conv:// ������������� - setConvOutput(layer, lastLayer); - break; - case samp:// ������������� - setSampOutput(layer, lastLayer); - break; - case output:// �������������,�������һ������ľ����� - setConvOutput(layer, lastLayer); - break; - default: - break; - } - } - } - - /** - * ���ݼ�¼ֵ���������������ֵ - * - * @param record - */ - private void setInLayerOutput(Record record) { - final Layer inputLayer = layers.get(0); - final Size mapSize = inputLayer.getMapSize(); - final double[] attr = record.getAttrs(); - if (attr.length != mapSize.x * mapSize.y) - throw new RuntimeException("���ݼ�¼�Ĵ�С�붨���map��С��һ��!"); - for (int i = 0; i < mapSize.x; i++) { - for (int j = 0; j < mapSize.y; j++) { - // ����¼���Ե�һά����Ū�ɶ�ά���� - inputLayer.setMapValue(0, i, j, attr[mapSize.x * i + j]); - } - } - } - - /* - * ������������ֵ,ÿ���̸߳���һ����map - */ - private void setConvOutput(final Layer layer, final Layer lastLayer) { - int mapNum = layer.getOutMapNum(); - final int lastMapNum = lastLayer.getOutMapNum(); - new TaskManager(mapNum) { - - @Override - public void process(int start, int end) { - for (int j = start; j < end; j++) { - double[][] sum = null;// ��ÿһ������map�ľ���������� - for (int i = 0; i < lastMapNum; i++) { - double[][] lastMap = lastLayer.getMap(i); - double[][] kernel = layer.getKernel(i, j); - if (sum == null) - sum = Util.convnValid(lastMap, kernel); - else - sum = Util.matrixOp( - Util.convnValid(lastMap, kernel), sum, - null, null, Util.plus); - } - final double bias = layer.getBias(j); - sum = Util.matrixOp(sum, new Operator() { - private static final long serialVersionUID = 2469461972825890810L; - - @Override - public double process(double value) { - return Util.sigmod(value + bias); - } - - }); - - layer.setMapValue(j, sum); - } - } - - }.start(); - - } - - /** - * ���ò���������ֵ���������ǶԾ�����ľ�ֵ���� - * - * @param layer - * @param lastLayer - */ - private void setSampOutput(final Layer layer, final Layer lastLayer) { - int lastMapNum = lastLayer.getOutMapNum(); - new TaskManager(lastMapNum) { - - @Override - public void process(int start, int end) { - for (int i = start; i < end; i++) { - double[][] lastMap = lastLayer.getMap(i); - Size scaleSize = layer.getScaleSize(); - // ��scaleSize������о�ֵ���� - double[][] sampMatrix = Util - .scaleMatrix(lastMap, scaleSize); - layer.setMapValue(i, sampMatrix); - } - } - - }.start(); - - } - - /** - * ����cnn�����ÿһ��IJ��� - * - * @param batchSize - * * @param classNum - * @param inputMapSize - */ - public void setup(int batchSize) { - Layer inputLayer = layers.get(0); - // ÿһ�㶼��Ҫ��ʼ�����map - inputLayer.initOutmaps(batchSize); - for (int i = 1; i < layers.size(); i++) { - Layer layer = layers.get(i); - Layer frontLayer = layers.get(i - 1); - int frontMapNum = frontLayer.getOutMapNum(); - switch (layer.getType()) { - case input: - break; - case conv: - // ����map�Ĵ�С - layer.setMapSize(frontLayer.getMapSize().subtract( - layer.getKernelSize(), 1)); - // ��ʼ�������ˣ�����frontMapNum*outMapNum�������� - - layer.initKernel(frontMapNum); - // ��ʼ��ƫ�ã�����frontMapNum*outMapNum��ƫ�� - layer.initBias(frontMapNum); - // batch��ÿ����¼��Ҫ����һ�ݲв� - layer.initErros(batchSize); - // ÿһ�㶼��Ҫ��ʼ�����map - layer.initOutmaps(batchSize); - break; - case samp: - // �������map��������һ����ͬ - layer.setOutMapNum(frontMapNum); - // ������map�Ĵ�С����һ��map�Ĵ�С����scale��С - layer.setMapSize(frontLayer.getMapSize().divide( - layer.getScaleSize())); - // batch��ÿ����¼��Ҫ����һ�ݲв� - layer.initErros(batchSize); - // ÿһ�㶼��Ҫ��ʼ�����map - layer.initOutmaps(batchSize); - break; - case output: - // ��ʼ��Ȩ�أ������ˣ��������ľ����˴�СΪ��һ���map��С - layer.initOutputKerkel(frontMapNum, frontLayer.getMapSize()); - // ��ʼ��ƫ�ã�����frontMapNum*outMapNum��ƫ�� - layer.initBias(frontMapNum); - // batch��ÿ����¼��Ҫ����һ�ݲв� - layer.initErros(batchSize); - // ÿһ�㶼��Ҫ��ʼ�����map - layer.initOutmaps(batchSize); - break; - } - } - } - - /** - * ������ģʽ�������,Ҫ�����ڶ������Ϊ�����������Ϊ������ - * - * @author jiqunpeng - * - * ����ʱ�䣺2014-7-8 ����4:54:29 - */ - public static class LayerBuilder { - private List mLayers; - - public LayerBuilder() { - mLayers = new ArrayList(); - } - - public LayerBuilder(Layer layer) { - this(); - mLayers.add(layer); - } - - public LayerBuilder addLayer(Layer layer) { - mLayers.add(layer); - return this; - } - } - - /** - * ���л�����ģ�� - * - * @param fileName - */ - public void saveModel(String fileName) { - try { - ObjectOutputStream oos = new ObjectOutputStream( - new FileOutputStream(fileName)); - oos.writeObject(this); - oos.flush(); - oos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - /** - * �����л�����ģ�� - * - * @param fileName - * @return - */ - public static CNN loadModel(String fileName) { - try { - ObjectInputStream in = new ObjectInputStream(new FileInputStream( - fileName)); - CNN cnn = (CNN) in.readObject(); - in.close(); - return cnn; - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/src/edu/hitsz/c102c/cnn/RunCNN.java b/src/edu/hitsz/c102c/cnn/RunCNN.java deleted file mode 100644 index 7f3a1c9..0000000 --- a/src/edu/hitsz/c102c/cnn/RunCNN.java +++ /dev/null @@ -1,51 +0,0 @@ -package edu.hitsz.c102c.cnn; - -import edu.hitsz.c102c.cnn.CNN.LayerBuilder; -import edu.hitsz.c102c.cnn.Layer.Size; -import edu.hitsz.c102c.dataset.Dataset; -import edu.hitsz.c102c.util.ConcurenceRunner; -import edu.hitsz.c102c.util.TimedTest; -import edu.hitsz.c102c.util.TimedTest.TestTask; - -public class RunCNN { - - public static void runCnn() { - //����һ������������ - LayerBuilder builder = new LayerBuilder(); - builder.addLayer(Layer.buildInputLayer(new Size(28, 28))); - builder.addLayer(Layer.buildConvLayer(6, new Size(5, 5))); - builder.addLayer(Layer.buildSampLayer(new Size(2, 2))); - builder.addLayer(Layer.buildConvLayer(12, new Size(5, 5))); - builder.addLayer(Layer.buildSampLayer(new Size(2, 2))); - builder.addLayer(Layer.buildOutputLayer(10)); - CNN cnn = new CNN(builder, 50); - - //�������ݼ� - String fileName = "dataset/train.format"; - Dataset dataset = Dataset.load(fileName, ",", 784); - cnn.train(dataset, 3);// - String modelName = "model/model.cnn"; - cnn.saveModel(modelName); - dataset.clear(); - dataset = null; - - //Ԥ�� - // CNN cnn = CNN.loadModel(modelName); - Dataset testset = Dataset.load("dataset/test.format", ",", -1); - cnn.predict(testset, "dataset/test.predict"); - } - - public static void main(String[] args) { - - new TimedTest(new TestTask() { - - @Override - public void process() { - runCnn(); - } - }, 1).test(); - ConcurenceRunner.stop(); - - } - -} diff --git a/src/edu/hitsz/c102c/dataset/Dataset.java b/src/edu/hitsz/c102c/dataset/Dataset.java deleted file mode 100644 index d0291c2..0000000 --- a/src/edu/hitsz/c102c/dataset/Dataset.java +++ /dev/null @@ -1,239 +0,0 @@ -package edu.hitsz.c102c.dataset; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class Dataset { - // �������� - private List records; - // ����±� - private int lableIndex; - - private double maxLable = -1; - - public Dataset(int classIndex) { - - this.lableIndex = classIndex; - records = new ArrayList(); - } - - public Dataset(List datas) { - this(); - for (double[] data : datas) { - append(new Record(data)); - } - } - - private Dataset() { - this.lableIndex = -1; - records = new ArrayList(); - } - - public int size() { - return records.size(); - } - - public int getLableIndex() { - return lableIndex; - } - - public void append(Record record) { - records.add(record); - } - - /** - * ������� - */ - public void clear() { - records.clear(); - } - - /** - * ����һ����¼ - * - * @param attrs - * ��¼������ - * @param lable - * ��¼����� - */ - public void append(double[] attrs, Double lable) { - records.add(new Record(attrs, lable)); - } - - public Iterator iter() { - return records.iterator(); - } - - /** - * ��ȡ��index����¼������ - * - * @param index - * @return - */ - public double[] getAttrs(int index) { - return records.get(index).getAttrs(); - } - - public Double getLable(int index) { - return records.get(index).getLable(); - } - - /** - * �������ݼ� - * - * @param filePath - * �ļ�����·�� - * @param tag - * �ֶηָ��� - * @param lableIndex - * ����±꣬��0��ʼ - * @return - */ - public static Dataset load(String filePath, String tag, int lableIndex) { - Dataset dataset = new Dataset(); - dataset.lableIndex = lableIndex; - File file = new File(filePath); - try { - - BufferedReader in = new BufferedReader(new FileReader(file)); - String line; - while ((line = in.readLine()) != null) { - String[] datas = line.split(tag); - if (datas.length == 0) - continue; - double[] data = new double[datas.length]; - for (int i = 0; i < datas.length; i++) - data[i] = Double.parseDouble(datas[i]); - Record record = dataset.new Record(data); - dataset.append(record); - } - in.close(); - - } catch (IOException e) { - e.printStackTrace(); - return null; - } - System.out.println("��������:" + dataset.size()); - return dataset; - } - - /** - * ���ݼ�¼(ʵ��),��¼�����Ժ�������,������Ϊ��һ�л������һ�л��߿� - * - * @author jiqunpeng - * - * ����ʱ�䣺2014-6-15 ����8:03:29 - */ - public class Record { - // �洢���� - private double[] attrs; - private Double lable; - - private Record(double[] attrs, Double lable) { - this.attrs = attrs; - this.lable = lable; - } - - public Record(double[] data) { - if (lableIndex == -1) - attrs = data; - else { - lable = data[lableIndex]; - if (lable > maxLable) - maxLable = lable; - if (lableIndex == 0) - attrs = Arrays.copyOfRange(data, 1, data.length); - else - attrs = Arrays.copyOfRange(data, 0, data.length - 1); - } - } - - /** - * �ü�¼������ - * - * @return - */ - public double[] getAttrs() { - return attrs; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("attrs:"); - sb.append(Arrays.toString(attrs)); - sb.append("lable:"); - sb.append(lable); - return sb.toString(); - } - - /** - * �ü�¼����� - * - * @return - */ - public Double getLable() { - if (lableIndex == -1) - return null; - return lable; - } - - /** - * �������ж����Ʊ��� - * - * @param n - * @return - */ - public int[] getEncodeTarget(int n) { - String binary = Integer.toBinaryString(lable.intValue()); - byte[] bytes = binary.getBytes(); - int[] encode = new int[n]; - int j = n; - for (int i = bytes.length - 1; i >= 0; i--) - encode[--j] = bytes[i] - '0'; - - return encode; - } - - public double[] getDoubleEncodeTarget(int n) { - String binary = Integer.toBinaryString(lable.intValue()); - byte[] bytes = binary.getBytes(); - double[] encode = new double[n]; - int j = n; - for (int i = bytes.length - 1; i >= 0; i--) - encode[--j] = bytes[i] - '0'; - - return encode; - } - - } - - public static void main(String[] args) { - Dataset d = new Dataset(); - d.lableIndex = 10; - Record r = d.new Record(new double[] { 3, 2, 2, 5, 4, 5, 3, 11, 3, 12, - 1 }); - int[] encode = r.getEncodeTarget(4); - - System.out.println(r.lable); - System.out.println(Arrays.toString(encode)); - } - - /** - * ��ȡ��index����¼ - * - * @param index - * @return - */ - public Record getRecord(int index) { - return records.get(index); - } - -} diff --git a/src/edu/hitsz/c102c/util/ConcurenceRunner.java b/src/edu/hitsz/c102c/util/ConcurenceRunner.java deleted file mode 100644 index 7a57a66..0000000 --- a/src/edu/hitsz/c102c/util/ConcurenceRunner.java +++ /dev/null @@ -1,93 +0,0 @@ -package edu.hitsz.c102c.util; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * �������й��� - * - * @author jiqunpeng - * - * ����ʱ�䣺2014-6-16 ����3:33:41 - */ -public class ConcurenceRunner { - - private static final ExecutorService exec; - public static final int cpuNum; - static { - cpuNum = Runtime.getRuntime().availableProcessors(); - // cpuNum = 1; - System.out.println("cpuNum:" + cpuNum); - exec = Executors.newFixedThreadPool(cpuNum); - } - - public static void run(Runnable task) { - exec.execute(task); - } - - public static void stop() { - exec.shutdown(); - } - - // public abstract static class Task implements - // Runnable { - // int start, end; - // - // public Task(int start, int end) { - // this.start = start; - // this.end = end; - // // Log.i("new Task", - // // "start "+start+" end "+end); - // } - // - // @Override - // public void run() { - // process(start, end); - // } - // - // public abstract void process(int start, int - // end); - // - // } - - public abstract static class TaskManager { - private int workLength; - - public TaskManager(int workLength) { - this.workLength = workLength; - } - - public void start() { - int runCpu = cpuNum < workLength ? cpuNum : 1; - // ��Ƭ��������ȡ�� - final CountDownLatch gate = new CountDownLatch(runCpu); - int fregLength = (workLength + runCpu - 1) / runCpu; - for (int cpu = 0; cpu < runCpu; cpu++) { - final int start = cpu * fregLength; - int tmp = (cpu + 1) * fregLength; - final int end = tmp <= workLength ? tmp : workLength; - Runnable task = new Runnable() { - - @Override - public void run() { - process(start, end); - gate.countDown(); - } - - }; - ConcurenceRunner.run(task); - } - try {// �ȴ������߳����� - gate.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - public abstract void process(int start, int end); - - } - -} diff --git a/src/edu/hitsz/c102c/util/Log.java b/src/edu/hitsz/c102c/util/Log.java deleted file mode 100644 index 9892816..0000000 --- a/src/edu/hitsz/c102c/util/Log.java +++ /dev/null @@ -1,16 +0,0 @@ -package edu.hitsz.c102c.util; - -import java.io.PrintStream; - -public class Log { - static PrintStream stream = System.out; - - public static void i(String tag,String msg){ - stream.println(tag+"\t"+msg); - } - - public static void i(String msg){ - stream.println(msg); - } - -} diff --git a/src/main/java/javacnn/cnn/CNN.java b/src/main/java/javacnn/cnn/CNN.java new file mode 100644 index 0000000..631362c --- /dev/null +++ b/src/main/java/javacnn/cnn/CNN.java @@ -0,0 +1,589 @@ +package javacnn.cnn; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javacnn.dataset.Dataset; +import javacnn.util.DotProgressIndicator; +import javacnn.util.Log; +import javacnn.util.ProgressIndicator; +import javacnn.util.Runner; +import javacnn.util.Util; + +public class CNN implements Serializable { + + private static final long serialVersionUID = 5L; + + private static final double LAMBDA = 0; + + private double ALPHA = 0.85; + + private final List layers; + private final int layerNum; + private final int batchSize; + + private final Util.Operator divide_batchSize; + private final Util.Operator multiply_alpha; + private final Util.Operator multiply_lambda; + + private transient Runner runner; + + private transient ProgressIndicator progressIndicator = new DotProgressIndicator(); + + public CNN(LayerBuilder layerBuilder, final int batchSize, final Runner runner) { + + this.layers = layerBuilder.layerList; + this.layerNum = layers.size(); + this.batchSize = batchSize; + + this.runner = runner; + + setup(batchSize); + + // --- + + final double _1_batchSize = 1. / batchSize; + + divide_batchSize = new Util.Operator() { + private static final long serialVersionUID = 7424011281732651055L; + + @Override + public double process(double value) { + return value * _1_batchSize; + } + + }; + + multiply_alpha = new Util.Operator() { + private static final long serialVersionUID = 5761368499808006552L; + + @Override + public double process(double value) { + return value * ALPHA; + } + + }; + + multiply_lambda = new Util.Operator() { + private static final long serialVersionUID = 4499087728362870577L; + + @Override + public double process(double value) { + return value * (1 - LAMBDA * ALPHA); + } + }; + } + + // === simple getters and setters === + + public void setRunner(final Runner runner) { + this.runner = runner; + } + + private Runner getRunner() { + if (runner == null) throw new NullPointerException("'runner' is null. Set runner before start training or test!"); + return runner; + } + + public ProgressIndicator getProgressIndicator() { + return progressIndicator; + } + + public void setProgressIndicator(final ProgressIndicator progressIndicator) { + this.progressIndicator = progressIndicator; + } + + // === business logic === + + public void train(final Dataset trainset, final int iterationCount) { + for (int iteration = 0; iteration < iterationCount; iteration++) { + + progressIndicator.start(); + + // separate trainset in batches of batchsize ... and round up the result + final int epochsNum = (trainset.size() + batchSize - 1) / batchSize; + + Log.info(iteration + "th iter epochsNum:" + epochsNum); + + int right = 0; + int count = 0; + + for (int epoch = 0; epoch < epochsNum; epoch++) { + + int[] randPerm = Util.randomPerm(trainset.size(), batchSize); + + Layer.prepareForNewBatch(); + + for (int index : randPerm) { + final boolean isRight = train(trainset.getRecord(index)); + if (isRight) right++; + count++; + Layer.prepareForNewRecord(); + } + + // After finishing a batch update weight + updateParas(); + + progressIndicator.progress(); + } + + progressIndicator.finished(); + + final double precision = ((double) right) / count; + + if (iteration % 10 == 1 && precision > 0.96) { + ALPHA = 0.001 + ALPHA * 0.9; // Adjust the quasi-learning rate dynamically + Log.info("Set alpha = " + ALPHA); + } + + Log.info("precision " + right + "/" + count + "=" + precision); + } + } + + public double test(final Dataset dataset) { + Layer.prepareForNewBatch(); + + final Iterator iterator = dataset.iterator(); + + int right = 0; + while (iterator.hasNext()) { + final Dataset.Record record = iterator.next(); + + final double[] out = propagate(record); + + if (record.getLabel().intValue() == Util.getMaxIndex(out)) { + right++; + } + } + + double p = 1.0 * right / dataset.size(); + + Log.info("precision", p + ""); + + return p; + } + + private double[] getOutput() { + final Layer outputLayer = layers.get(layerNum - 1); + + final int mapNum = outputLayer.getOutMapNum(); + final double[] out = new double[mapNum]; + for (int m = 0; m < mapNum; m++) { + final double[][] outmap = outputLayer.getMap(m); + out[m] = outmap[0][0]; + } + return out; + } + + // TODO: Move this method to other/new class (reduce CNN-class to the minimal CNN-logic) + public void predict(Dataset testset, String fileName) { + Log.info("begin predict"); + try { + // final int max = layers.get(layerNum - 1).getClassNum(); + final PrintWriter writer = new PrintWriter(new File(fileName)); + + Layer.prepareForNewBatch(); + + final Iterator iter = testset.iterator(); + while (iter.hasNext()) { + final Dataset.Record record = iter.next(); + final double[] out = propagate(record); + // int label = + // Util.binaryArray2int(out); + final int label = Util.getMaxIndex(out); + // if (label >= max) + // label = label - (1 << (out.length - + // 1)); + writer.write(label + "\n"); + } + writer.flush(); + writer.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + Log.info("end predict"); + } + + private boolean train(Dataset.Record record) { + forward(record); + + return backPropagation(record); + } + + private boolean backPropagation(Dataset.Record record) { + boolean result = setOutLayerErrors(record); + setHiddenLayerErrors(); + return result; + } + + private void updateParas() { + for (int l = 1; l < layerNum; l++) { + Layer layer = layers.get(l); + Layer lastLayer = layers.get(l - 1); + switch (layer.getType()) { + case conv: + case output: + updateKernels(layer, lastLayer); + updateBias(layer); + break; + default: + break; + } + } + } + + private void updateBias(final Layer layer) { + final double[][][][] errors = layer.getErrors(); + int mapNum = layer.getOutMapNum(); + + final Process processor = + new Process() { + @Override + public void process(int start, int end) { + for (int j = start; j < end; j++) { + final double[][] error = Util.sum(errors, j); + // update offset + final double deltaBias = Util.sum(error) / batchSize; + final double bias = layer.getBias(j) + ALPHA * deltaBias; + layer.setBias(j, bias); + } + } + }; + + getRunner().startProcess(mapNum, processor); + } + + private void updateKernels(final Layer layer, final Layer lastLayer) { + final int mapNum = layer.getOutMapNum(); + final int lastMapNum = lastLayer.getOutMapNum(); + + final Process process = new Process() { + @Override + public void process(int start, int end) { + for (int j = start; j < end; j++) { + for (int i = 0; i < lastMapNum; i++) { + double[][] deltaKernel = null; + for (int r = 0; r < batchSize; r++) { + final double[][] error = layer.getError(r, j); + if (deltaKernel == null) + deltaKernel = Util.convnValid(lastLayer.getMap(r, i), error); + else { + deltaKernel = Util.matrixOp(Util.convnValid(lastLayer.getMap(r, i), error), deltaKernel, null, null, Util.plus); + } + } + + deltaKernel = Util.matrixOp(deltaKernel, divide_batchSize); + final double[][] kernel = layer.getKernel(i, j); + deltaKernel = Util.matrixOp(kernel, deltaKernel, multiply_lambda, multiply_alpha, Util.plus); + layer.setKernel(i, j, deltaKernel); + } + } + + } + }; + + getRunner().startProcess(mapNum, process); + } + + private void setHiddenLayerErrors() { + for (int l = layerNum - 2; l > 0; l--) { + final Layer layer = layers.get(l); + final Layer nextLayer = layers.get(l + 1); + switch (layer.getType()) { + case samp: + setSampErrors(layer, nextLayer); + break; + case conv: + setConvErrors(layer, nextLayer); + break; + default: + break; + } + } + } + + private void setSampErrors(final Layer layer, final Layer nextLayer) { + final int mapNum = layer.getOutMapNum(); + final int nextMapNum = nextLayer.getOutMapNum(); + + final Process process = new Process() { + @Override + public void process(int start, int end) { + for (int i = start; i < end; i++) { + double[][] sum = null;// ��ÿһ������������ + for (int j = 0; j < nextMapNum; j++) { + final double[][] nextError = nextLayer.getError(j); + final double[][] kernel = nextLayer.getKernel(i, j); + if (sum == null) + sum = Util.convnFull(nextError, Util.rot180(kernel)); + else + sum = Util.matrixOp(Util.convnFull(nextError, Util.rot180(kernel)), sum, null, null, Util.plus); + } + layer.setError(i, sum); + } + } + + }; + + getRunner().startProcess(mapNum, process); + } + + private void setConvErrors(final Layer layer, final Layer nextLayer) { + final int mapNum = layer.getOutMapNum(); + + final Process process = new Process() { + @Override + public void process(int start, int end) { + for (int m = start; m < end; m++) { + final Layer.Size scale = nextLayer.getScaleSize(); + final double[][] nextError = nextLayer.getError(m); + final double[][] map = layer.getMap(m); + double[][] outMatrix = Util.matrixOp(map, Util.cloneMatrix(map), null, Util.one_value, Util.multiply); + outMatrix = Util.matrixOp(outMatrix, Util.kronecker(nextError, scale), null, null, Util.multiply); + layer.setError(m, outMatrix); + } + } + }; + + getRunner().startProcess(mapNum, process); + } + + private boolean setOutLayerErrors(final Dataset.Record record) { + + final Layer outputLayer = layers.get(layerNum - 1); + final int mapNum = outputLayer.getOutMapNum(); + final double[] target = new double[mapNum]; + final double[] outmaps = new double[mapNum]; + + for (int m = 0; m < mapNum; m++) { + final double[][] outmap = outputLayer.getMap(m); + outmaps[m] = outmap[0][0]; + } + + final int label = record.getLabel().intValue(); + + target[label] = 1; + + for (int m = 0; m < mapNum; m++) { + outputLayer.setError(m, 0, 0, outmaps[m] * (1 - outmaps[m]) * (target[m] - outmaps[m])); + } + + return label == Util.getMaxIndex(outmaps); + } + + /** + * Propagate given values through the network. + * Returns the results. + * For each input it returns the set of output values. + * + * @param inputs A list of vectors of input values + * @return A list of results of the network corresponding to each input vector + */ + public double[][] propagate(final double[][] inputs) { + final double[][] results = new double[inputs.length][]; + + int index = 0; + for (final double[] input : inputs) { + final Dataset.Record record = new Dataset.Record(input, -1.); + results[index] = propagate(record); + index++; + } + + return results; + } + + /** + * Propagate given values through the network. + * Returns the result. + * + * @param inputs A vector of input values + * @return The result of the network + */ + public double[] propagate(final double[] inputs) { + final Dataset.Record record = new Dataset.Record(inputs, -1.); + + return propagate(record); + } + + /** + * Propagate given Record through the network. + * Returns the result. + * + * @param record A Record + * @return The result of the network + */ + public double[] propagate(final Dataset.Record record) { + forward(record); + + return getOutput(); + } + + private void forward(final Dataset.Record record) { + setInLayerOutput(record); + + for (int l = 1; l < layers.size(); l++) { + final Layer layer = layers.get(l); + final Layer lastLayer = layers.get(l - 1); + + switch (layer.getType()) { + case conv: + setConvOutput(layer, lastLayer); + break; + + case samp: + setSampOutput(layer, lastLayer); + break; + + case output: + setConvOutput(layer, lastLayer); + break; + + default: + break; + } + } + } + + private void setInLayerOutput(final Dataset.Record record) { + final Layer inputLayer = layers.get(0); + final Layer.Size mapSize = inputLayer.getMapSize(); + + final double[] attr = record.getAttrs(); + + if (attr.length != mapSize.x * mapSize.y) { + throw new RuntimeException("The size of the data record does not match the size of the map defined!"); + } + + for (int i = 0; i < mapSize.x; i++) { + for (int j = 0; j < mapSize.y; j++) { + inputLayer.setMapValue(0, i, j, attr[mapSize.x * i + j]); + } + } + } + + /** + * Compute the output of the convolutional layer, each thread is responsible for part of the map + */ + private void setConvOutput(final Layer layer, final Layer lastLayer) { + final int mapNum = layer.getOutMapNum(); + final int lastMapNum = lastLayer.getOutMapNum(); + + final Process process = new Process() { + @Override + public void process(int start, int end) { + for (int j = start; j < end; j++) { + double[][] sum = null; + for (int i = 0; i < lastMapNum; i++) { + final double[][] lastMap = lastLayer.getMap(i); + final double[][] kernel = layer.getKernel(i, j); + if (sum == null) { + sum = Util.convnValid(lastMap, kernel); + } else { + sum = Util.matrixOp(Util.convnValid(lastMap, kernel), sum, null, null, Util.plus); + } + } + final double bias = layer.getBias(j); + sum = Util + .matrixOp( + sum, + new Util.Operator() { + private static final long serialVersionUID = 2469461972825890810L; + + @Override + public double process(double value) { + return Util.sigmod(value + bias); + } + } + ); + + layer.setMapValue(j, sum); + } + } + }; + + getRunner().startProcess(mapNum, process); + } + + private void setSampOutput(final Layer layer, final Layer lastLayer) { + final int lastMapNum = lastLayer.getOutMapNum(); + + final Process process = new Process() { + @Override + public void process(int start, int end) { + for (int i = start; i < end; i++) { + final double[][] lastMap = lastLayer.getMap(i); + final Layer.Size scaleSize = layer.getScaleSize(); + final double[][] sampMatrix = Util.scaleMatrix(lastMap, scaleSize); + layer.setMapValue(i, sampMatrix); + } + } + }; + + getRunner().startProcess(lastMapNum, process); + } + + private void setup(final int batchSize) { + final Layer inputLayer = layers.get(0); + + inputLayer.initOutmaps(batchSize); + + for (int i = 1; i < layers.size(); i++) { + + final Layer layer = layers.get(i); + final Layer frontLayer = layers.get(i - 1); + + final int frontMapNum = frontLayer.getOutMapNum(); + switch (layer.getType()) { + case input: + break; + case conv: + layer.setMapSize(frontLayer.getMapSize().subtract(layer.getKernelSize(), 1)); + layer.initKernel(frontMapNum); + layer.initBias(frontMapNum); + layer.initErros(batchSize); + layer.initOutmaps(batchSize); + break; + + case samp: + layer.setOutMapNum(frontMapNum); + layer.setMapSize(frontLayer.getMapSize().divide(layer.getScaleSize())); + layer.initErros(batchSize); + layer.initOutmaps(batchSize); + break; + + case output: + layer.initOutputKerkel(frontMapNum, frontLayer.getMapSize()); + layer.initBias(frontMapNum); + layer.initErros(batchSize); + layer.initOutmaps(batchSize); + break; + } + } + } + + // === inner classes === + + public static class LayerBuilder { + private List layerList; + + public LayerBuilder() { + layerList = new ArrayList<>(); + } + + public LayerBuilder(Layer layer) { + this(); + layerList.add(layer); + } + + public LayerBuilder addLayer(Layer layer) { + layerList.add(layer); + return this; + } + } + +} diff --git a/src/main/java/javacnn/cnn/CNNLoader.java b/src/main/java/javacnn/cnn/CNNLoader.java new file mode 100644 index 0000000..b084bba --- /dev/null +++ b/src/main/java/javacnn/cnn/CNNLoader.java @@ -0,0 +1,36 @@ +package javacnn.cnn; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; + +public class CNNLoader { + + public static void saveModel(final String fileName, final CNN cnn) throws IOException { + saveModel(cnn, new FileOutputStream(fileName)); + } + + public static void saveModel(final CNN cnn, final OutputStream outputStream) throws IOException { + ObjectOutputStream oos = new ObjectOutputStream(outputStream); + oos.writeObject(cnn); + oos.flush(); + oos.close(); + } + + public static CNN loadModel(final String fileName) throws IOException, ClassNotFoundException { + return loadModel(new FileInputStream(fileName)); + } + + public static CNN loadModel(final InputStream inputStream) throws IOException, ClassNotFoundException { + final ObjectInputStream in = new ObjectInputStream(inputStream); + final CNN cnn = (CNN) in.readObject(); + in.close(); + + return cnn; + } + +} diff --git a/src/edu/hitsz/c102c/cnn/Layer.java b/src/main/java/javacnn/cnn/Layer.java similarity index 64% rename from src/edu/hitsz/c102c/cnn/Layer.java rename to src/main/java/javacnn/cnn/Layer.java index adf78e4..5d9599f 100644 --- a/src/edu/hitsz/c102c/cnn/Layer.java +++ b/src/main/java/javacnn/cnn/Layer.java @@ -1,75 +1,56 @@ -package edu.hitsz.c102c.cnn; +package javacnn.cnn; import java.io.Serializable; -import edu.hitsz.c102c.util.Log; -import edu.hitsz.c102c.util.Util; +import javacnn.util.Log; +import javacnn.util.Util; /** - * cnn����IJ� - * + * cnn����IJ� + * * @author jiqunpeng - * - * ����ʱ�䣺2014-7-8 ����3:58:46 + *

+ * ����ʱ�䣺2014-7-8 ����3:58:46 */ public class Layer implements Serializable { /** - * + * */ private static final long serialVersionUID = -5747622503947497069L; - private LayerType type;// ������� - private int outMapNum;// ���map�ĸ��� - private Size mapSize;// map�Ĵ�С - private Size kernelSize;// �����˴�С��ֻ�о������� - private Size scaleSize;// ������С��ֻ�в������� - private double[][][][] kernel;// �����ˣ�ֻ�о������������� - private double[] bias;// ÿ��map��Ӧһ��ƫ�ã�ֻ�о������������� - // �������batch�����map��outmaps[0][0]��ʾ��һ����¼ѵ���µ�0�����map + private LayerType type; + private int outMapNum; + private Size mapSize; + private Size kernelSize; + private Size scaleSize; + private double[][][][] kernel; + private double[] bias; private double[][][][] outmaps; - // �в��matlab toolbox��d��Ӧ private double[][][][] errors; - private static int recordInBatch = 0;// ��¼��ǰѵ������batch�ĵڼ�����¼ + private static int recordInBatch = 0; - private int classNum = -1;// ������ + private int classNum = -1; private Layer() { } - /** - * ׼����һ��batch��ѵ�� - */ public static void prepareForNewBatch() { recordInBatch = 0; } - /** - * ׼����һ����¼��ѵ�� - */ public static void prepareForNewRecord() { recordInBatch++; } - /** - * ��ʼ������� - * - * @param mapSize - * @return - */ public static Layer buildInputLayer(Size mapSize) { Layer layer = new Layer(); layer.type = LayerType.input; - layer.outMapNum = 1;// ������map����Ϊ1����һ��ͼ + layer.outMapNum = 1;// ������map����Ϊ1����һ��ͼ layer.setMapSize(mapSize);// return layer; } - /** - * ��������� - * - * @return - */ public static Layer buildConvLayer(int outMapNum, Size kernelSize) { Layer layer = new Layer(); layer.type = LayerType.conv; @@ -78,12 +59,6 @@ public static Layer buildConvLayer(int outMapNum, Size kernelSize) { return layer; } - /** - * ��������� - * - * @param scaleSize - * @return - */ public static Layer buildSampLayer(Size scaleSize) { Layer layer = new Layer(); layer.type = LayerType.samp; @@ -91,11 +66,6 @@ public static Layer buildSampLayer(Size scaleSize) { return layer; } - /** - * ���������,���������������ĸ��������������Ԫ�ĸ��� - * - * @return - */ public static Layer buildOutputLayer(int classNum) { Layer layer = new Layer(); layer.classNum = classNum; @@ -106,86 +76,44 @@ public static Layer buildOutputLayer(int classNum) { // while ((1 << outMapNum) < classNum) // outMapNum += 1; // layer.outMapNum = outMapNum; - Log.i("outMapNum:" + layer.outMapNum); + Log.info("outMapNum:" + layer.outMapNum); return layer; } - /** - * ��ȡmap�Ĵ�С - * - * @return - */ public Size getMapSize() { return mapSize; } - /** - * ����map�Ĵ�С - * - * @param mapSize - */ public void setMapSize(Size mapSize) { this.mapSize = mapSize; } - /** - * ��ȡ������� - * - * @return - */ public LayerType getType() { return type; } - /** - * ��ȡ����������� - * - * @return - */ - public int getOutMapNum() { return outMapNum; } - /** - * �������map�ĸ��� - * - * @param outMapNum - */ public void setOutMapNum(int outMapNum) { this.outMapNum = outMapNum; } - /** - * ��ȡ�����˵Ĵ�С��ֻ�о�������kernelSize���������δnull - * - * @return - */ public Size getKernelSize() { return kernelSize; } - /** - * ��ȡ������С��ֻ�в�������scaleSize���������δnull - * - * @return - */ public Size getScaleSize() { return scaleSize; } enum LayerType { - // ���������ͣ�����㡢����㡢�����㡢������ input, output, conv, samp } - /** - * �����˻��߲�����scale�Ĵ�С,��������Բ���.���Ͱ�ȫ�����Ժ󲻿��޸� - * - * @author jiqunpeng - * - * ����ʱ�䣺2014-7-8 ����4:11:00 - */ + // --- + public static class Size implements Serializable { private static final long serialVersionUID = -209157832162004118L; @@ -197,30 +125,34 @@ public Size(int x, int y) { this.y = y; } + @Override public String toString() { - StringBuilder s = new StringBuilder("Size(").append(" x = ") - .append(x).append(" y= ").append(y).append(")"); - return s.toString(); + return "Size{" + + "x=" + x + + ", y=" + y + + '}'; } /** - * ����scaleSize�õ�һ���µ�Size��Ҫ��this.x��this. - * y�ֱܷ�scaleSize.x��scaleSize.y���� - * + * ����scaleSize�õ�һ���µ�Size��Ҫ��this.x��this. + * y�ֱܷ�scaleSize.x��scaleSize.y���� + * * @param scaleSize * @return */ public Size divide(Size scaleSize) { int x = this.x / scaleSize.x; int y = this.y / scaleSize.y; - if (x * scaleSize.x != this.x || y * scaleSize.y != this.y) - throw new RuntimeException(this + "��������" + scaleSize); + if (x * scaleSize.x != this.x || y * scaleSize.y != this.y) { + throw new RuntimeException(this + " can not be divisible " + scaleSize); + } + return new Size(x, y); } /** - * ��ȥsize��С����x��y�ֱ𸽼�һ��ֵappend - * + * ��ȥsize��С����x��y�ֱ𸽼�һ��ֵappend + * * @param size * @param append * @return @@ -233,8 +165,8 @@ public Size subtract(Size size, int append) { } /** - * �����ʼ�������� - * + * �����ʼ������� + * * @param frontMapNum */ public void initKernel(int frontMapNum) { @@ -244,12 +176,12 @@ public void initKernel(int frontMapNum) { this.kernel = new double[frontMapNum][outMapNum][kernelSize.x][kernelSize.y]; for (int i = 0; i < frontMapNum; i++) for (int j = 0; j < outMapNum; j++) - kernel[i][j] = Util.randomMatrix(kernelSize.x, kernelSize.y,true); + kernel[i][j] = Util.randomMatrix(kernelSize.x, kernelSize.y, true); } /** - * �����ľ����˵Ĵ�С����һ���map��С - * + * �����ľ���˵Ĵ�С����һ���map��С + * * @param frontMapNum * @param size */ @@ -261,12 +193,12 @@ public void initOutputKerkel(int frontMapNum, Size size) { this.kernel = new double[frontMapNum][outMapNum][kernelSize.x][kernelSize.y]; for (int i = 0; i < frontMapNum; i++) for (int j = 0; j < outMapNum; j++) - kernel[i][j] = Util.randomMatrix(kernelSize.x, kernelSize.y,false); + kernel[i][j] = Util.randomMatrix(kernelSize.x, kernelSize.y, false); } /** - * ��ʼ��ƫ�� - * + * ��ʼ��ƫ�� + * * @param frontMapNum */ public void initBias(int frontMapNum) { @@ -274,8 +206,8 @@ public void initBias(int frontMapNum) { } /** - * ��ʼ�����map - * + * ��ʼ�����map + * * @param batchSize */ public void initOutmaps(int batchSize) { @@ -283,14 +215,11 @@ public void initOutmaps(int batchSize) { } /** - * ����mapֵ - * - * @param mapNo - * �ڼ���map - * @param mapX - * map�ĸ� - * @param mapY - * map�Ŀ� + * ����mapֵ + * + * @param mapNo �ڼ���map + * @param mapX map�ĸ� + * @param mapY map�Ŀ� * @param value */ public void setMapValue(int mapNo, int mapX, int mapY, double value) { @@ -300,8 +229,8 @@ public void setMapValue(int mapNo, int mapX, int mapY, double value) { static int count = 0; /** - * �Ծ�����ʽ���õ�mapNo��map��ֵ - * + * �Ծ�����ʽ���õ�mapNo��map��ֵ + * * @param mapNo * @param outMatrix */ @@ -312,9 +241,9 @@ public void setMapValue(int mapNo, double[][] outMatrix) { } /** - * ��ȡ��index��map���󡣴������ܿ��ǣ�û�з��ظ��ƶ��󣬶���ֱ�ӷ������ã����ö�������� - * �����޸�outmaps�������޸������setMapValue(...) - * + * ��ȡ��index��map���󡣴������ܿ��ǣ�û�з��ظ��ƶ��󣬶���ֱ�ӷ������ã����ö�������� + * �����޸�outmaps�������޸������setMapValue(...) + * * @param index * @return */ @@ -323,12 +252,10 @@ public double[][] getMap(int index) { } /** - * ��ȡǰһ���i��map����ǰ���j��map�ľ����� - * - * @param i - * ��һ���map�±� - * @param j - * ��ǰ���map�±� + * ��ȡǰһ���i��map����ǰ���j��map�ľ���� + * + * @param i ��һ���map�±� + * @param j ��ǰ���map�±� * @return */ public double[][] getKernel(int i, int j) { @@ -336,8 +263,8 @@ public double[][] getKernel(int i, int j) { } /** - * ���òв�ֵ - * + * ���òв�ֵ + * * @param mapNo * @param mapX * @param mapY @@ -348,8 +275,8 @@ public void setError(int mapNo, int mapX, int mapY, double value) { } /** - * ��map�������ʽ���òв�ֵ - * + * ��map�������ʽ���òв�ֵ + * * @param mapNo * @param matrix */ @@ -360,9 +287,9 @@ public void setError(int mapNo, double[][] matrix) { } /** - * ��ȡ��mapNo��map�IJв�.û�з��ظ��ƶ��󣬶���ֱ�ӷ������ã����ö�������� - * �����޸�errors�������޸������setError(...) - * + * ��ȡ��mapNo��map�IJв�.û�з��ظ��ƶ��󣬶���ֱ�ӷ������ã����ö�������� + * �����޸�errors�������޸������setError(...) + * * @param mapNo * @return */ @@ -371,8 +298,8 @@ public double[][] getError(int mapNo) { } /** - * ��ȡ����(ÿ����¼��ÿ��map)�IJв� - * + * ��ȡ����(ÿ����¼��ÿ��map)�IJв� + * * @return */ public double[][][][] getErrors() { @@ -380,8 +307,8 @@ public double[][][][] getErrors() { } /** - * ��ʼ���в����� - * + * ��ʼ���в����� + * * @param batchSize */ public void initErros(int batchSize) { @@ -389,7 +316,6 @@ public void initErros(int batchSize) { } /** - * * @param lastMapNo * @param mapNo * @param kernel @@ -399,8 +325,8 @@ public void setKernel(int lastMapNo, int mapNo, double[][] kernel) { } /** - * ��ȡ��mapNo�� - * + * ��ȡ��mapNo�� + * * @param mapNo * @return */ @@ -409,8 +335,8 @@ public double getBias(int mapNo) { } /** - * ���õ�mapNo��map��ƫ��ֵ - * + * ���õ�mapNo��map��ƫ��ֵ + * * @param mapNo * @param value */ @@ -419,8 +345,8 @@ public void setBias(int mapNo, double value) { } /** - * ��ȡbatch����map���� - * + * ��ȡbatch����map���� + * * @return */ @@ -429,8 +355,8 @@ public double[][][][] getMaps() { } /** - * ��ȡ��recordId��¼�µ�mapNo�IJв� - * + * ��ȡ��recordId��¼�µ�mapNo�IJв� + * * @param recordId * @param mapNo * @return @@ -440,8 +366,8 @@ public double[][] getError(int recordId, int mapNo) { } /** - * ��ȡ��recordId��¼�µ�mapNo�����map - * + * ��ȡ��recordId��¼�µ�mapNo�����map + * * @param recordId * @param mapNo * @return @@ -451,8 +377,8 @@ public double[][] getMap(int recordId, int mapNo) { } /** - * ��ȡ������ - * + * ��ȡ������ + * * @return */ public int getClassNum() { @@ -460,8 +386,8 @@ public int getClassNum() { } /** - * ��ȡ���еľ����� - * + * ��ȡ���еľ���� + * * @return */ public double[][][][] getKernel() { diff --git a/src/main/java/javacnn/cnn/Process.java b/src/main/java/javacnn/cnn/Process.java new file mode 100644 index 0000000..0ba7194 --- /dev/null +++ b/src/main/java/javacnn/cnn/Process.java @@ -0,0 +1,11 @@ +package javacnn.cnn; + +/** + *

+ * Created: 2018-02-19 08:29 + * + * @author Ralf Th. Pietsch <ratopi@abwesend.de> + */ +public interface Process { + void process(int start, int end); +} diff --git a/src/main/java/javacnn/dataset/Dataset.java b/src/main/java/javacnn/dataset/Dataset.java new file mode 100644 index 0000000..877d47b --- /dev/null +++ b/src/main/java/javacnn/dataset/Dataset.java @@ -0,0 +1,89 @@ +package javacnn.dataset; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +public class Dataset { + private List records; + + public Dataset() { + records = new ArrayList<>(); + } + + public Dataset(final List datas, final List labels) { + this(); + + if (datas.size() != labels.size()) { + throw new IllegalArgumentException("Lengths differs: " + datas.size() + " datas and " + labels.size() + " labels"); + } + + for (int i = 0; i < datas.size(); i++) { + final double[] data = datas.get(i); + final Double label = labels.get(i); + append(new Record(data, label)); + } + } + + public int size() { + return records.size(); + } + + public void append(Record record) { + records.add(record); + } + + public void clear() { + records.clear(); + } + + public void append(double[] attrs, Double label) { + records.add(new Record(attrs, label)); + } + + public Iterator iterator() { + return records.iterator(); + } + + public double[] getAttrs(int index) { + return records.get(index).getAttrs(); + } + + public Double getLabel(int index) { + return records.get(index).getLabel(); + } + + public Record getRecord(int index) { + return records.get(index); + } + + // --- + + public static class Record { + private double[] attrs; + private Double label; + + public Record(double[] attrs, Double label) { + this.attrs = attrs; + this.label = label; + } + + public double[] getAttrs() { + return attrs; + } + + public Double getLabel() { + return label; + } + + @Override + public String toString() { + return "Record{" + + "attrs=" + Arrays.toString(attrs) + + ", label=" + label + + '}'; + } + } + +} diff --git a/src/main/java/javacnn/dataset/DatasetLoader.java b/src/main/java/javacnn/dataset/DatasetLoader.java new file mode 100644 index 0000000..f5a663d --- /dev/null +++ b/src/main/java/javacnn/dataset/DatasetLoader.java @@ -0,0 +1,41 @@ +package javacnn.dataset; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + +public class DatasetLoader { + public static Dataset load(final String filePath, final String tag, final int labelIndex) throws IOException { + final Dataset dataset = new Dataset(); + + final BufferedReader in = new BufferedReader(new FileReader(filePath)); + + String line; + while ((line = in.readLine()) != null) { + + final String[] datas = line.split(tag); + + if (datas.length == 0) { + continue; + } + + final int vectorLength = labelIndex < 0 ? datas.length : datas.length - 1; + + final double[] data = new double[vectorLength]; + + for (int i = 0; i < vectorLength; i++) { + data[i] = Double.parseDouble(datas[i]); + } + + final Double label = labelIndex < 0 ? null : Double.parseDouble(datas[labelIndex]); + + dataset.append(data, label); + } + in.close(); + + System.out.println("Read " + dataset.size() + " records"); + + return dataset; + } + +} diff --git a/src/main/java/javacnn/util/ConcurenceRunner.java b/src/main/java/javacnn/util/ConcurenceRunner.java new file mode 100644 index 0000000..e364195 --- /dev/null +++ b/src/main/java/javacnn/util/ConcurenceRunner.java @@ -0,0 +1,75 @@ +package javacnn.util; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javacnn.cnn.Process; + +/** + * Concurrent running tools + *

+ * Created: 2014-6-16 at 3:33:41 PM + * + * @author jiqunpeng + */ +public class ConcurenceRunner implements Runner { + + private final ExecutorService exec; + private final int threadCount; + + /** + * Starting ConcurrenceRunner with one thread for each CPU. + */ + public ConcurenceRunner() { + this(Runtime.getRuntime().availableProcessors()); + } + + /** + * Starting ConcurenceRunner with the given count of threads. + * + * @param threadCount Threads to start (must be > 0). + */ + public ConcurenceRunner(final int threadCount) { + this.threadCount = threadCount; + exec = Executors.newFixedThreadPool(this.threadCount); + } + + public void shutdown() { + exec.shutdown(); + } + + @Override + public void startProcess(final int mapNum, final Process process) { + final int runCpu = threadCount < mapNum ? threadCount : 1; + + // Fragment length rounded up + final CountDownLatch gate = new CountDownLatch(runCpu); + + final int fregLength = (mapNum + runCpu - 1) / runCpu; + + for (int cpu = 0; cpu < runCpu; cpu++) { + final int start = cpu * fregLength; + + final int tmp = (cpu + 1) * fregLength; + final int end = tmp <= mapNum ? tmp : mapNum; + + final Runnable task = new Runnable() { + @Override + public void run() { + process.process(start, end); + gate.countDown(); + } + }; + + exec.execute(task); + } + try {// Wait for all threads to finish running + gate.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/javacnn/util/DirectRunner.java b/src/main/java/javacnn/util/DirectRunner.java new file mode 100644 index 0000000..ad8bd4c --- /dev/null +++ b/src/main/java/javacnn/util/DirectRunner.java @@ -0,0 +1,29 @@ +package javacnn.util; + +import javacnn.cnn.Process; + +/** + *

+ * Created: 20.02.2018 11:03 + * + * @author Ralf Th. Pietsch <ratopi@abwesend.de> + */ +public class DirectRunner implements Runner { + + @Override + public void startProcess(final int mapNum, final Process process) { + final int runCpu = 1; + + // Fragment length rounded up + final int fregLength = (mapNum + runCpu - 1) / runCpu; + + for (int cpu = 0; cpu < runCpu; cpu++) { + final int start = cpu * fregLength; + + final int tmp = (cpu + 1) * fregLength; + final int end = tmp <= mapNum ? tmp : mapNum; + + process.process(start, end); + } + } +} diff --git a/src/main/java/javacnn/util/DotProgressIndicator.java b/src/main/java/javacnn/util/DotProgressIndicator.java new file mode 100644 index 0000000..5996de8 --- /dev/null +++ b/src/main/java/javacnn/util/DotProgressIndicator.java @@ -0,0 +1,47 @@ +package javacnn.util; + +import java.io.Serializable; + +/** + *

+ * Created: 19.02.2018 10:53 + * + * @author Ralf Th. Pietsch <ratopi@abwesend.de> + */ +public class DotProgressIndicator implements ProgressIndicator, Serializable { + + private static final long serialVersionUID = 1L; + + private int cycle; + + private int count = 0; + + + public DotProgressIndicator() { + this(50); + } + + public DotProgressIndicator(final int cycle) { + this.cycle = cycle; + } + + + @Override + public void start() { + count = 0; + } + + @Override + public void progress() { + count++; + if (count > cycle) { + System.out.print("."); + count = 0; + } + } + + @Override + public void finished() { + System.out.println(); + } +} diff --git a/src/main/java/javacnn/util/Log.java b/src/main/java/javacnn/util/Log.java new file mode 100644 index 0000000..683cc86 --- /dev/null +++ b/src/main/java/javacnn/util/Log.java @@ -0,0 +1,22 @@ +package javacnn.util; + +import java.io.PrintStream; + +public class Log { + private static final PrintStream stream = System.out; + + private static boolean on = false; + + public static void switchOn() { + on = true; + } + + public static void info(String tag, String msg) { + if (on) stream.println(tag + "\t" + msg); + } + + public static void info(String msg) { + if (on) stream.println(msg); + } + +} diff --git a/src/main/java/javacnn/util/ProgressIndicator.java b/src/main/java/javacnn/util/ProgressIndicator.java new file mode 100644 index 0000000..1bb4af4 --- /dev/null +++ b/src/main/java/javacnn/util/ProgressIndicator.java @@ -0,0 +1,14 @@ +package javacnn.util; + +/** + * Interface for feedback progress of any kind + *

+ * Created: 19.02.2018 10:52 + * + * @author Ralf Th. Pietsch <ratopi@abwesend.de> + */ +public interface ProgressIndicator { + void start(); + void progress(); + void finished(); +} diff --git a/src/main/java/javacnn/util/Runner.java b/src/main/java/javacnn/util/Runner.java new file mode 100644 index 0000000..b404a49 --- /dev/null +++ b/src/main/java/javacnn/util/Runner.java @@ -0,0 +1,13 @@ +package javacnn.util; + +import javacnn.cnn.Process; + +/** + *

+ * Created: 2018-02-19 08:57 + * + * @author Ralf Th. Pietsch <ratopi@abwesend.de> + */ +public interface Runner { + void startProcess(int mapNum, Process process); +} diff --git a/src/edu/hitsz/c102c/util/TestArray.java b/src/main/java/javacnn/util/TestArray.java similarity index 73% rename from src/edu/hitsz/c102c/util/TestArray.java rename to src/main/java/javacnn/util/TestArray.java index b946432..4ccf55f 100644 --- a/src/edu/hitsz/c102c/util/TestArray.java +++ b/src/main/java/javacnn/util/TestArray.java @@ -1,15 +1,15 @@ -package edu.hitsz.c102c.util; +package javacnn.util; import java.util.Locale; -import edu.hitsz.c102c.util.TimedTest.TestTask; +import javacnn.util.TimedTest.TestTask; /** - * ����Ԫ��ֱ�ӷ���������ͨ���������������Ч�ʣ� ���ۣ�������ʽ���ʲ�û�н����ٶ� + * ����Ԫ��ֱ�ӷ���������ͨ���������������Ч�ʣ� ���ۣ�������ʽ���ʲ�û�н����ٶ� * * @author jiqunpeng * - * ����ʱ�䣺2014-7-9 ����3:18:30 + * ����ʱ�䣺2014-7-9 ����3:18:30 */ public class TestArray { double[][] data; @@ -35,7 +35,7 @@ private void useFunc() { } public static void main(String[] args) { - String a = "aAdfa��_"; + String a = "aAdfa��_"; System.out.println(a.toUpperCase(Locale.CHINA)); double[][] d = new double[3][]; // d[0] = new double[] { 1,2,3 }; diff --git a/src/edu/hitsz/c102c/util/TimedTest.java b/src/main/java/javacnn/util/TimedTest.java similarity index 74% rename from src/edu/hitsz/c102c/util/TimedTest.java rename to src/main/java/javacnn/util/TimedTest.java index 71125aa..ea5959c 100644 --- a/src/edu/hitsz/c102c/util/TimedTest.java +++ b/src/main/java/javacnn/util/TimedTest.java @@ -1,11 +1,11 @@ -package edu.hitsz.c102c.util; +package javacnn.util; /** - * ��ʱ�IJ��Թ��� + * ��ʱ�IJ��Թ��� * * @author jiqunpeng * - * ����ʱ�䣺2014-7-8 ����8:21:56 + * ����ʱ�䣺2014-7-8 ����8:21:56 */ public class TimedTest { private int repeat; @@ -26,6 +26,6 @@ public void test() { task.process(); } double cost = (System.currentTimeMillis() - t) / 1000.0; - Log.i("cost ", cost + "s"); + Log.info("cost ", cost + "s"); } } diff --git a/src/edu/hitsz/c102c/util/Util.java b/src/main/java/javacnn/util/Util.java similarity index 84% rename from src/edu/hitsz/c102c/util/Util.java rename to src/main/java/javacnn/util/Util.java index e0d0077..62b3020 100644 --- a/src/edu/hitsz/c102c/util/Util.java +++ b/src/main/java/javacnn/util/Util.java @@ -1,27 +1,26 @@ -package edu.hitsz.c102c.util; +package javacnn.util; import java.io.Serializable; import java.util.Arrays; import java.util.HashSet; import java.util.Random; import java.util.Set; -import edu.hitsz.c102c.cnn.Layer.Size; -import edu.hitsz.c102c.util.TimedTest.TestTask; +import javacnn.cnn.Layer.Size; public class Util { /** - * �����ӦԪ�����ʱ��ÿ��Ԫ���ϵIJ��� + * �����ӦԪ�����ʱ��ÿ��Ԫ���ϵIJ��� * * @author jiqunpeng * - * ����ʱ�䣺2014-7-9 ����9:28:35 + * ����ʱ�䣺2014-7-9 ����9:28:35 */ public interface Operator extends Serializable { public double process(double value); } - // ����ÿ��Ԫ��value������1-value�IJ��� + // ����ÿ��Ԫ��value������1-value�IJ��� public static final Operator one_value = new Operator() { /** * @@ -34,7 +33,7 @@ public double process(double value) { } }; - // digmod���� + // digmod���� public static final Operator digmod = new Operator() { /** * @@ -52,7 +51,7 @@ interface OperatorOnTwo extends Serializable { } /** - * ��������ӦԪ�صļӷ����� + * ��������ӦԪ�صļӷ����� */ public static final OperatorOnTwo plus = new OperatorOnTwo() { /** @@ -66,7 +65,7 @@ public double process(double a, double b) { } }; /** - * ��������ӦԪ�صij˷����� + * ��������ӦԪ�صij˷����� */ public static OperatorOnTwo multiply = new OperatorOnTwo() { /** @@ -81,7 +80,7 @@ public double process(double a, double b) { }; /** - * ��������ӦԪ�صļ������� + * ��������ӦԪ�صļ������� */ public static OperatorOnTwo minus = new OperatorOnTwo() { /** @@ -105,7 +104,7 @@ public static void printMatrix(double[][] matrix) { } /** - * �Ծ������180����ת,����matrix�ĸ����ϸ��ƣ������ԭ���ľ�������޸� + * �Ծ������180����ת,����matrix�ĸ����ϸ��ƣ������ԭ���ľ�������޸� * * @param matrix */ @@ -113,7 +112,7 @@ public static double[][] rot180(double[][] matrix) { matrix = cloneMatrix(matrix); int m = matrix.length; int n = matrix[0].length; - // ���жԳƽ��н��� + // ���жԳƽ��н��� for (int i = 0; i < m; i++) { for (int j = 0; j < n / 2; j++) { double tmp = matrix[i][j]; @@ -121,7 +120,7 @@ public static double[][] rot180(double[][] matrix) { matrix[i][n - 1 - j] = tmp; } } - // ���жԳƽ��н��� + // ���жԳƽ��н��� for (int j = 0; j < n; j++) { for (int i = 0; i < m / 2; i++) { double tmp = matrix[i][j]; @@ -135,7 +134,7 @@ public static double[][] rot180(double[][] matrix) { private static Random r = new Random(2); /** - * �����ʼ������ + * �����ʼ������ * * @param x * @param y @@ -147,7 +146,7 @@ public static double[][] randomMatrix(int x, int y, boolean b) { int tag = 1; for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { - // ���ֵ��[-0.05,0.05)֮�䣬��Ȩ�س�ʼ��ֵ��С���������ڱ������� + // ���ֵ��[-0.05,0.05)֮�䣬��Ȩ�س�ʼ��ֵ��С���������ڱ������� matrix[i][j] = (r.nextDouble() - 0.05) / 10; // matrix[i][j] = tag * 0.5; // if (b) @@ -160,7 +159,7 @@ public static double[][] randomMatrix(int x, int y, boolean b) { } /** - * �����ʼ��һά���� + * �����ʼ��һά���� * * @param len * @return @@ -175,7 +174,7 @@ public static double[] randomArray(int len) { } /** - * ������еij����������ȡbatchSize��[0,size)���� + * ������еij����������ȡbatchSize��[0,size)���� * * @param size * @param batchSize @@ -194,7 +193,7 @@ public static int[] randomPerm(int size, int batchSize) { } /** - * ���ƾ��� + * ���ƾ��� * * @param matrix * @return @@ -214,7 +213,7 @@ public static double[][] cloneMatrix(final double[][] matrix) { } /** - * �Ե���������в��� + * �Ե���������в��� * * @param ma * @param operator @@ -233,15 +232,15 @@ public static double[][] matrixOp(final double[][] ma, Operator operator) { } /** - * ����ά����ͬ�ľ����ӦԪ�ز���,�õ��Ľ������mb�У���mb[i][j] = (op_a + * ����ά����ͬ�ľ����ӦԪ�ز���,�õ��Ľ������mb�У���mb[i][j] = (op_a * ma[i][j]) op (op_b mb[i][j]) * * @param ma * @param mb * @param operatorB - * �ڵ�mb�����ϵIJ��� + * �ڵ�mb�����ϵIJ��� * @param operatorA - * ��ma����Ԫ���ϵIJ��� + * ��ma����Ԫ���ϵIJ��� * @return * */ @@ -251,7 +250,7 @@ public static double[][] matrixOp(final double[][] ma, final double[][] mb, final int m = ma.length; int n = ma[0].length; if (m != mb.length || n != mb[0].length) - throw new RuntimeException("���������С��һ�� ma.length:" + ma.length + throw new RuntimeException("���������С��һ�� ma.length:" + ma.length + " mb.length:" + mb.length); for (int i = 0; i < m; i++) { @@ -269,7 +268,7 @@ public static double[][] matrixOp(final double[][] ma, final double[][] mb, } /** - * �����ڿ˻�,�Ծ��������չ + * �����ڿ˻�,�Ծ��������չ * * @param matrix * @param scale @@ -293,7 +292,7 @@ public static double[][] kronecker(final double[][] matrix, final Size scale) { } /** - * �Ծ�����о�ֵ��С + * �Ծ�����о�ֵ��С * * @param matrix * @param scaleSize @@ -307,7 +306,7 @@ public static double[][] scaleMatrix(final double[][] matrix, final int sn = n / scale.y; final double[][] outMatrix = new double[sm][sn]; if (sm * scale.x != m || sn * scale.y != n) - throw new RuntimeException("scale��������matrix"); + throw new RuntimeException("scale��������matrix"); final int size = scale.x * scale.y; for (int i = 0; i < sm; i++) { for (int j = 0; j < sn; j++) { @@ -324,7 +323,7 @@ public static double[][] scaleMatrix(final double[][] matrix, } /** - * ����fullģʽ�ľ��� + * ����fullģʽ�ľ�� * * @param matrix * @param kernel @@ -336,7 +335,7 @@ public static double[][] convnFull(double[][] matrix, int n = matrix[0].length; final int km = kernel.length; final int kn = kernel[0].length; - // ��չ���� + // ��չ���� final double[][] extendMatrix = new double[m + 2 * (km - 1)][n + 2 * (kn - 1)]; for (int i = 0; i < m; i++) { @@ -347,7 +346,7 @@ public static double[][] convnFull(double[][] matrix, } /** - * ����validģʽ�ľ��� + * ����validģʽ�ľ�� * * @param matrix * @param kernel @@ -360,11 +359,11 @@ public static double[][] convnValid(final double[][] matrix, int n = matrix[0].length; final int km = kernel.length; final int kn = kernel[0].length; - // ��Ҫ������������ + // ��Ҫ����������� int kns = n - kn + 1; - // ��Ҫ������������ + // ��Ҫ����������� final int kms = m - km + 1; - // ������� + // ������� final double[][] outMatrix = new double[kms][kns]; for (int i = 0; i < kms; i++) { @@ -383,7 +382,7 @@ public static double[][] convnValid(final double[][] matrix, } /** - * ��ά����ľ���,����Ҫ�����������һά��ͬ + * ��ά����ľ��,����Ҫ�����������һά��ͬ * * @param matrix * @param kernel @@ -401,8 +400,8 @@ public static double[][] convnValid(final double[][][][] matrix, int kns = n - kn + 1; int khs = h - kh + 1; if (matrix.length != kernel.length) - throw new RuntimeException("������������ڵ�һά�ϲ�ͬ"); - // ������� + throw new RuntimeException("�����������ڵ�һά�ϲ�ͬ"); + // ������� final double[][][] outMatrix = new double[kms][kns][khs]; for (int i = 0; i < kms; i++) { for (int j = 0; j < kns; j++) @@ -426,10 +425,10 @@ public static double sigmod(double x) { } /** - * �Ծ���Ԫ����� + * �Ծ���Ԫ����� * * @param error - * @return ע�������ͺܿ��ܻ���� + * @return ע�������ͺܿ��ܻ���� */ public static double sum(double[][] error) { @@ -445,7 +444,7 @@ public static double sum(double[][] error) { } /** - * ��errors[...][j]Ԫ����� + * ��errors[...][j]Ԫ����� * * @param errors * @param j @@ -482,7 +481,7 @@ public static int binaryArray2int(double[] array) { } /** - * ���Ծ���,���Խ����4���²������еľ�����߲���2�� + * ���Ծ��,���Խ����4���²������еľ����߲���2�� */ private static void testConvn() { int count = 1; @@ -608,7 +607,7 @@ public static void main(String[] args) { } /** - * ȡ����Ԫ�ص��±� + * ȡ����Ԫ�ص��±� * * @param out * @return diff --git a/src/test/dataset/readme.md b/src/test/dataset/readme.md new file mode 100644 index 0000000..01c8d6d --- /dev/null +++ b/src/test/dataset/readme.md @@ -0,0 +1,3 @@ +The dataset is part of MNIST from kaggle Digit Recognizer competition: +* "train.format" is the train set, which has been binarized. +* "test.format" is the test set, which has been binarized. diff --git a/dataset/test.format b/src/test/dataset/test.format similarity index 100% rename from dataset/test.format rename to src/test/dataset/test.format diff --git a/dataset/train.format b/src/test/dataset/train.format similarity index 100% rename from dataset/train.format rename to src/test/dataset/train.format diff --git a/src/test/java/javacnn/RunCNN.java b/src/test/java/javacnn/RunCNN.java new file mode 100644 index 0000000..cae9051 --- /dev/null +++ b/src/test/java/javacnn/RunCNN.java @@ -0,0 +1,52 @@ +package javacnn; + +import java.io.IOException; + +import javacnn.cnn.CNN; +import javacnn.cnn.CNNLoader; +import javacnn.cnn.Layer; +import javacnn.dataset.Dataset; +import javacnn.dataset.DatasetLoader; +import javacnn.util.ConcurenceRunner; + +public class RunCNN { + + public static void main(String[] args) throws IOException, ClassNotFoundException { + + final ConcurenceRunner concurenceRunner = new ConcurenceRunner(); + + try { + + final CNN.LayerBuilder builder = + new CNN.LayerBuilder() + .addLayer(Layer.buildInputLayer(new Layer.Size(28, 28))) + .addLayer(Layer.buildConvLayer(6, new Layer.Size(5, 5))) + .addLayer(Layer.buildSampLayer(new Layer.Size(2, 2))) + .addLayer(Layer.buildConvLayer(12, new Layer.Size(5, 5))) + .addLayer(Layer.buildSampLayer(new Layer.Size(2, 2))) + .addLayer(Layer.buildOutputLayer(10)); + + final CNN cnn = new CNN(builder, 50, concurenceRunner); + // final CNN cnn = new CNN(builder, 50, new DirectRunner()); + + final String fileName = "src/test/dataset/train.format"; + final Dataset dataset = DatasetLoader.load(fileName, ",", 784); + cnn.train(dataset, 3); + + CNNLoader.saveModel("src/test/model.cnn", cnn); + dataset.clear(); + + /* + final CNN cnn = CNNLoader.loadModel("model.cnn"); + cnn.setRunner(concurenceRunner); + */ + + final Dataset testset = DatasetLoader.load("src/test/dataset/test.format", ",", -1); + cnn.predict(testset, "src/test/dataset/test.predict"); + + } finally { + concurenceRunner.shutdown(); + } + } + +}