diff --git a/Cargo.lock b/Cargo.lock index fa7a13a5f..473281ef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "advapi32-sys" version = "0.2.0" @@ -14,11 +12,11 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ - "memchr 2.3.4", + "memchr 2.4.0", ] [[package]] @@ -108,12 +106,12 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" dependencies = [ "lazy_static", - "memchr 2.3.4", + "memchr 2.4.0", "regex-automata", "serde", ] @@ -165,13 +163,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.11" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ + "libc", "num-integer", "num-traits", "time", + "winapi 0.3.9", ] [[package]] @@ -334,6 +334,16 @@ dependencies = [ "walkdir", ] +[[package]] +name = "coz" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef55b3fe2f5477d59e12bc792e8b3c95a25bd099eadcfae006ecea136de76e2" +dependencies = [ + "libc", + "once_cell", +] + [[package]] name = "cpp" version = "0.5.6" @@ -486,9 +496,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -499,9 +509,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" dependencies = [ "autocfg", "cfg-if 1.0.0", @@ -552,7 +562,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" dependencies = [ - "memchr 2.3.4", + "memchr 2.4.0", ] [[package]] @@ -634,7 +644,7 @@ checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.6", + "redox_syscall 0.2.7", "winapi 0.3.9", ] @@ -846,6 +856,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "locale" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fdbe492a9c0238da900a1165c42fc5067161ce292678a6fe80921f30fe307fd" +dependencies = [ + "libc", +] + [[package]] name = "log" version = "0.4.14" @@ -893,9 +912,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" [[package]] name = "memoffset" @@ -1170,7 +1189,7 @@ version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ - "unicode-xid 0.2.1", + "unicode-xid 0.2.2", ] [[package]] @@ -1340,9 +1359,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" +checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2" dependencies = [ "bitflags", ] @@ -1353,17 +1372,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" dependencies = [ - "redox_syscall 0.2.6", + "redox_syscall 0.2.7", ] [[package]] name = "regex" -version = "1.4.6" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" +checksum = "ce5f1ceb7f74abbce32601642fcf8e8508a8a8991e0621c7d750295b9095702b" dependencies = [ "aho-corasick", - "memchr 2.3.4", + "memchr 2.4.0", "regex-syntax", ] @@ -1378,9 +1397,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.23" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remove_dir_all" @@ -1453,6 +1472,9 @@ name = "serde" version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_cbor" @@ -1551,6 +1573,9 @@ name = "smallvec" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +dependencies = [ + "serde", +] [[package]] name = "strsim" @@ -1578,13 +1603,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.70" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" +checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" dependencies = [ "proc-macro2", "quote 1.0.9", - "unicode-xid 0.2.1", + "unicode-xid 0.2.2", ] [[package]] @@ -1638,7 +1663,7 @@ checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" dependencies = [ "libc", "numtoa", - "redox_syscall 0.2.6", + "redox_syscall 0.2.7", "redox_termios", ] @@ -1687,12 +1712,11 @@ dependencies = [ [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall 0.1.57", "winapi 0.3.9", ] @@ -1732,9 +1756,9 @@ checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "unindent" @@ -1784,6 +1808,8 @@ dependencies = [ name = "uu_base64" version = "0.0.6" dependencies = [ + "clap", + "uu_base32", "uucore", "uucore_procs", ] @@ -1900,7 +1926,9 @@ dependencies = [ name = "uu_cut" version = "0.0.6" dependencies = [ + "bstr", "clap", + "memchr 2.4.0", "uucore", "uucore_procs", ] @@ -2002,6 +2030,7 @@ dependencies = [ name = "uu_factor" version = "0.0.6" dependencies = [ + "coz", "criterion", "num-traits", "paste", @@ -2134,6 +2163,7 @@ dependencies = [ name = "uu_kill" version = "0.0.6" dependencies = [ + "clap", "libc", "uucore", "uucore_procs", @@ -2143,6 +2173,7 @@ dependencies = [ name = "uu_link" version = "0.0.6" dependencies = [ + "clap", "libc", "uucore", "uucore_procs", @@ -2172,15 +2203,16 @@ name = "uu_ls" version = "0.0.6" dependencies = [ "atty", + "chrono", "clap", "globset", "lazy_static", + "locale", "lscolors", "number_prefix", "once_cell", "term_grid", "termsize", - "time", "unicode-width", "uucore", "uucore_procs", @@ -2268,7 +2300,7 @@ dependencies = [ "aho-corasick", "clap", "libc", - "memchr 2.3.4", + "memchr 2.4.0", "regex", "regex-syntax", "uucore", @@ -2340,6 +2372,7 @@ dependencies = [ name = "uu_pinky" version = "0.0.6" dependencies = [ + "clap", "uucore", "uucore_procs", ] @@ -2369,7 +2402,7 @@ dependencies = [ "aho-corasick", "clap", "libc", - "memchr 2.3.4", + "memchr 2.4.0", "regex", "regex-syntax", "uucore", @@ -2484,7 +2517,10 @@ dependencies = [ "rand 0.7.3", "rayon", "semver", + "serde", + "serde_json", "smallvec 1.6.1", + "tempdir", "unicode-width", "uucore", "uucore_procs", diff --git a/README.md b/README.md index 12dfb5609..95dc036fd 100644 --- a/README.md +++ b/README.md @@ -429,6 +429,7 @@ This is an auto-generated table showing which binaries compile for each target-t |windows-msvc|i686|y|y|y|y|y| | | | |y|y|y|y|y|y|y|y|y| |y|y|y| |y|y|y|y| |y|y|y|y| | |y| |y|y|y|y|y| | |y|y|y| |y| |y|y|y|y| | |y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| | |y|y|y|y|y|y| |y|y|y|y|y| |y|y|y| |y| |y| |y|y| |windows-gnu|x86_64|y|y|y|y|y| | | | |y|y|y|y|y|y|y|y|y| |y|y|y| |y|y|y|y| |y|y|y|y| | |y| |y|y|y|y|y| | |y|y|y| |y| |y|y|y|y| | |y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| | |y|y|y|y|y|y| |y|y|y|y|y|y|y|y|y| |y| |y| |y|y| |windows-msvc|x86_64|y|y|y|y|y| | | | |y|y|y|y|y|y|y|y|y| |y|y|y| |y|y|y|y| |y|y|y|y| | |y| |y|y|y|y|y| | |y|y|y| |y| |y|y|y|y| | |y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| | |y|y|y|y|y|y| |y|y|y|y|y| |y|y|y| |y| |y| |y|y| +|apple MacOS|aarch64|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| |y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| |apple MacOS|x86_64|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| |y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| |freebsd|x86_64|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| |netbsd|x86_64|y|y|y|y|y|y|y|y| |y|y|y|y|y|y| |y|y|y|y|y|y| |y|y|y|y|y|y|y|y|y| |y|y| |y|y|y|y|y|y|y|y|y|y|y|y| |y|y|y|y|y| |y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y|y| |y|y|y|y|y|y| |y|y|y| | |y| |y|y| diff --git a/docs/compiles_table.py b/docs/compiles_table.py index 0cbfdf0e9..a051287c9 100644 --- a/docs/compiles_table.py +++ b/docs/compiles_table.py @@ -26,6 +26,7 @@ TARGETS = [ "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", # Apple + "aarch64-apple-darwin", "x86_64-apple-darwin", "aarch64-apple-ios", "x86_64-apple-ios", @@ -231,4 +232,4 @@ if __name__ == "__main__": prev_table, _, _ = load_csv(CACHE_PATH) new_table = merge_tables(prev_table, table) - save_csv(CACHE_PATH, new_table) \ No newline at end of file + save_csv(CACHE_PATH, new_table) diff --git a/src/uu/base32/src/base32.rs b/src/uu/base32/src/base32.rs index 6d9f7f08f..f0e187c31 100644 --- a/src/uu/base32/src/base32.rs +++ b/src/uu/base32/src/base32.rs @@ -7,19 +7,14 @@ #[macro_use] extern crate uucore; + +use std::io::{stdin, Read}; + use uucore::encoding::Format; -use uucore::InvalidEncodingHandling; -use std::fs::File; -use std::io::{stdin, BufReader}; -use std::path::Path; +pub mod base_common; -use clap::{App, Arg}; - -mod base_common; - -static SUMMARY: &str = "Base32 encode or decode FILE, or standard input, to standard output."; -static LONG_HELP: &str = " +static ABOUT: &str = " With no FILE, or when FILE is -, read standard input. The data are encoded as described for the base32 alphabet in RFC @@ -30,126 +25,41 @@ static LONG_HELP: &str = " "; static VERSION: &str = env!("CARGO_PKG_VERSION"); +static BASE_CMD_PARSE_ERROR: i32 = 1; + fn get_usage() -> String { format!("{0} [OPTION]... [FILE]", executable!()) } -pub mod options { - pub static DECODE: &str = "decode"; - pub static WRAP: &str = "wrap"; - pub static IGNORE_GARBAGE: &str = "ignore-garbage"; - pub static FILE: &str = "file"; -} - -struct Config { - decode: bool, - ignore_garbage: bool, - wrap_cols: Option, - to_read: Option, -} - -impl Config { - fn from(options: clap::ArgMatches) -> Config { - let file: Option = match options.values_of(options::FILE) { - Some(mut values) => { - let name = values.next().unwrap(); - if values.len() != 0 { - crash!(3, "extra operand ‘{}’", name); - } - - if name == "-" { - None - } else { - if !Path::exists(Path::new(name)) { - crash!(2, "{}: No such file or directory", name); - } - Some(name.to_owned()) - } - } - None => None, - }; - - let cols = match options.value_of(options::WRAP) { - Some(num) => match num.parse::() { - Ok(n) => Some(n), - Err(e) => { - crash!(1, "invalid wrap size: ‘{}’: {}", num, e); - } - }, - None => None, - }; - - Config { - decode: options.is_present(options::DECODE), - ignore_garbage: options.is_present(options::IGNORE_GARBAGE), - wrap_cols: cols, - to_read: file, - } - } -} - pub fn uumain(args: impl uucore::Args) -> i32 { let format = Format::Base32; let usage = get_usage(); - let app = App::new(executable!()) - .version(VERSION) - .about(SUMMARY) - .usage(&usage[..]) - .about(LONG_HELP) - // Format arguments. - .arg( - Arg::with_name(options::DECODE) - .short("d") - .long(options::DECODE) - .help("decode data"), - ) - .arg( - Arg::with_name(options::IGNORE_GARBAGE) - .short("i") - .long(options::IGNORE_GARBAGE) - .help("when decoding, ignore non-alphabetic characters"), - ) - .arg( - Arg::with_name(options::WRAP) - .short("w") - .long(options::WRAP) - .takes_value(true) - .help( - "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)", - ), - ) - // "multiple" arguments are used to check whether there is more than one - // file passed in. - .arg(Arg::with_name(options::FILE).index(1).multiple(true)); + let name = executable!(); - let arg_list = args - .collect_str(InvalidEncodingHandling::ConvertLossy) - .accept_any(); - let config: Config = Config::from(app.get_matches_from(arg_list)); - match config.to_read { - // Read from file. - Some(name) => { - let file_buf = safe_unwrap!(File::open(Path::new(&name))); - let mut input = BufReader::new(file_buf); - base_common::handle_input( - &mut input, - format, - config.wrap_cols, - config.ignore_garbage, - config.decode, - ); + let config_result: Result = + base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage); + + if config_result.is_err() { + match config_result { + Ok(_) => panic!(), + Err(s) => crash!(BASE_CMD_PARSE_ERROR, "{}", s), } - // stdin - None => { - base_common::handle_input( - &mut stdin().lock(), - format, - config.wrap_cols, - config.ignore_garbage, - config.decode, - ); - } - }; + } + + // Create a reference to stdin so we can return a locked stdin from + // parse_base_cmd_args + let stdin_raw = stdin(); + let config = config_result.unwrap(); + let mut input: Box = base_common::get_input(&config, &stdin_raw); + + base_common::handle_input( + &mut input, + format, + config.wrap_cols, + config.ignore_garbage, + config.decode, + name, + ); 0 } diff --git a/src/uu/base32/src/base_common.rs b/src/uu/base32/src/base_common.rs index a4b49e499..ee5fe8675 100644 --- a/src/uu/base32/src/base_common.rs +++ b/src/uu/base32/src/base_common.rs @@ -10,6 +10,122 @@ use std::io::{stdout, Read, Write}; use uucore::encoding::{wrap_print, Data, Format}; +use uucore::InvalidEncodingHandling; + +use std::fs::File; +use std::io::{BufReader, Stdin}; +use std::path::Path; + +use clap::{App, Arg}; + +// Config. +pub struct Config { + pub decode: bool, + pub ignore_garbage: bool, + pub wrap_cols: Option, + pub to_read: Option, +} + +pub mod options { + pub static DECODE: &str = "decode"; + pub static WRAP: &str = "wrap"; + pub static IGNORE_GARBAGE: &str = "ignore-garbage"; + pub static FILE: &str = "file"; +} + +impl Config { + fn from(options: clap::ArgMatches) -> Result { + let file: Option = match options.values_of(options::FILE) { + Some(mut values) => { + let name = values.next().unwrap(); + if values.len() != 0 { + return Err(format!("extra operand ‘{}’", name)); + } + + if name == "-" { + None + } else { + if !Path::exists(Path::new(name)) { + return Err(format!("{}: No such file or directory", name)); + } + Some(name.to_owned()) + } + } + None => None, + }; + + let cols = match options.value_of(options::WRAP) { + Some(num) => match num.parse::() { + Ok(n) => Some(n), + Err(e) => { + return Err(format!("Invalid wrap size: ‘{}’: {}", num, e)); + } + }, + None => None, + }; + + Ok(Config { + decode: options.is_present(options::DECODE), + ignore_garbage: options.is_present(options::IGNORE_GARBAGE), + wrap_cols: cols, + to_read: file, + }) + } +} + +pub fn parse_base_cmd_args( + args: impl uucore::Args, + name: &str, + version: &str, + about: &str, + usage: &str, +) -> Result { + let app = App::new(name) + .version(version) + .about(about) + .usage(usage) + // Format arguments. + .arg( + Arg::with_name(options::DECODE) + .short("d") + .long(options::DECODE) + .help("decode data"), + ) + .arg( + Arg::with_name(options::IGNORE_GARBAGE) + .short("i") + .long(options::IGNORE_GARBAGE) + .help("when decoding, ignore non-alphabetic characters"), + ) + .arg( + Arg::with_name(options::WRAP) + .short("w") + .long(options::WRAP) + .takes_value(true) + .help( + "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)", + ), + ) + // "multiple" arguments are used to check whether there is more than one + // file passed in. + .arg(Arg::with_name(options::FILE).index(1).multiple(true)); + let arg_list = args + .collect_str(InvalidEncodingHandling::ConvertLossy) + .accept_any(); + Config::from(app.get_matches_from(arg_list)) +} + +pub fn get_input<'a>(config: &Config, stdin_ref: &'a Stdin) -> Box { + match &config.to_read { + Some(name) => { + let file_buf = safe_unwrap!(File::open(Path::new(name))); + Box::new(BufReader::new(file_buf)) // as Box + } + None => { + Box::new(stdin_ref.lock()) // as Box + } + } +} pub fn handle_input( input: &mut R, @@ -17,6 +133,7 @@ pub fn handle_input( line_wrap: Option, ignore_garbage: bool, decode: bool, + name: &str, ) { let mut data = Data::new(input, format).ignore_garbage(ignore_garbage); if let Some(wrap) = line_wrap { @@ -31,10 +148,14 @@ pub fn handle_input( Ok(s) => { if stdout().write_all(&s).is_err() { // on windows console, writing invalid utf8 returns an error - crash!(1, "Cannot write non-utf8 data"); + eprintln!("{}: error: Cannot write non-utf8 data", name); + exit!(1) } } - Err(_) => crash!(1, "invalid input"), + Err(_) => { + eprintln!("{}: error: invalid input", name); + exit!(1) + } } } } diff --git a/src/uu/base64/Cargo.toml b/src/uu/base64/Cargo.toml index 841ab140c..d4ee69f03 100644 --- a/src/uu/base64/Cargo.toml +++ b/src/uu/base64/Cargo.toml @@ -15,8 +15,10 @@ edition = "2018" path = "src/base64.rs" [dependencies] +clap = "2.33" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features = ["encoding"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +uu_base32 = { version=">=0.0.6", package="uu_base32", path="../base32"} [[bin]] name = "base64" diff --git a/src/uu/base64/src/base64.rs b/src/uu/base64/src/base64.rs index 61a8dc5cb..810df4fe8 100644 --- a/src/uu/base64/src/base64.rs +++ b/src/uu/base64/src/base64.rs @@ -8,14 +8,14 @@ #[macro_use] extern crate uucore; + +use uu_base32::base_common; + use uucore::encoding::Format; -use uucore::InvalidEncodingHandling; -mod base_common; +use std::io::{stdin, Read}; -static SYNTAX: &str = "[OPTION]... [FILE]"; -static SUMMARY: &str = "Base64 encode or decode FILE, or standard input, to standard output."; -static LONG_HELP: &str = " +static ABOUT: &str = " With no FILE, or when FILE is -, read standard input. The data are encoded as described for the base64 alphabet in RFC @@ -24,14 +24,42 @@ static LONG_HELP: &str = " to attempt to recover from any other non-alphabet bytes in the encoded stream. "; +static VERSION: &str = env!("CARGO_PKG_VERSION"); + +static BASE_CMD_PARSE_ERROR: i32 = 1; + +fn get_usage() -> String { + format!("{0} [OPTION]... [FILE]", executable!()) +} pub fn uumain(args: impl uucore::Args) -> i32 { - base_common::execute( - args.collect_str(InvalidEncodingHandling::Ignore) - .accept_any(), - SYNTAX, - SUMMARY, - LONG_HELP, - Format::Base64, - ) + let format = Format::Base64; + let usage = get_usage(); + let name = executable!(); + let config_result: Result = + base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage); + + if config_result.is_err() { + match config_result { + Ok(_) => panic!(), + Err(s) => crash!(BASE_CMD_PARSE_ERROR, "{}", s), + } + } + + // Create a reference to stdin so we can return a locked stdin from + // parse_base_cmd_args + let stdin_raw = stdin(); + let config = config_result.unwrap(); + let mut input: Box = base_common::get_input(&config, &stdin_raw); + + base_common::handle_input( + &mut input, + format, + config.wrap_cols, + config.ignore_garbage, + config.decode, + name, + ); + + 0 } diff --git a/src/uu/base64/src/base_common.rs b/src/uu/base64/src/base_common.rs deleted file mode 100644 index 3f1436fb2..000000000 --- a/src/uu/base64/src/base_common.rs +++ /dev/null @@ -1,97 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// (c) Jordy Dickinson -// (c) Jian Zeng -// (c) Alex Lyon -// -// For the full copyright and license information, please view the LICENSE file -// that was distributed with this source code. - -use std::fs::File; -use std::io::{stdin, stdout, BufReader, Read, Write}; -use std::path::Path; - -use uucore::encoding::{wrap_print, Data, Format}; - -pub fn execute( - args: Vec, - syntax: &str, - summary: &str, - long_help: &str, - format: Format, -) -> i32 { - let matches = app!(syntax, summary, long_help) - .optflag("d", "decode", "decode data") - .optflag( - "i", - "ignore-garbage", - "when decoding, ignore non-alphabetic characters", - ) - .optopt( - "w", - "wrap", - "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)", - "COLS", - ) - .parse(args); - - let line_wrap = matches.opt_str("wrap").map(|s| match s.parse() { - Ok(n) => n, - Err(e) => { - crash!(1, "invalid wrap size: ‘{}’: {}", s, e); - } - }); - let ignore_garbage = matches.opt_present("ignore-garbage"); - let decode = matches.opt_present("decode"); - - if matches.free.len() > 1 { - show_usage_error!("extra operand ‘{}’", matches.free[0]); - return 1; - } - - if matches.free.is_empty() || &matches.free[0][..] == "-" { - let stdin_raw = stdin(); - handle_input( - &mut stdin_raw.lock(), - format, - line_wrap, - ignore_garbage, - decode, - ); - } else { - let path = Path::new(matches.free[0].as_str()); - let file_buf = safe_unwrap!(File::open(&path)); - let mut input = BufReader::new(file_buf); - handle_input(&mut input, format, line_wrap, ignore_garbage, decode); - }; - - 0 -} - -fn handle_input( - input: &mut R, - format: Format, - line_wrap: Option, - ignore_garbage: bool, - decode: bool, -) { - let mut data = Data::new(input, format).ignore_garbage(ignore_garbage); - if let Some(wrap) = line_wrap { - data = data.line_wrap(wrap); - } - - if !decode { - let encoded = data.encode(); - wrap_print(&data, encoded); - } else { - match data.decode() { - Ok(s) => { - if stdout().write_all(&s).is_err() { - // on windows console, writing invalid utf8 returns an error - crash!(1, "Cannot write non-utf8 data"); - } - } - Err(_) => crash!(1, "invalid input"), - } - } -} diff --git a/src/uu/basename/Cargo.toml b/src/uu/basename/Cargo.toml index 92d0ca4cd..0072619b7 100644 --- a/src/uu/basename/Cargo.toml +++ b/src/uu/basename/Cargo.toml @@ -15,6 +15,7 @@ edition = "2018" path = "src/basename.rs" [dependencies] +clap = "2.33.2" uucore = { version=">=0.0.8", package="uucore", path="../../uucore" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/basename/src/basename.rs b/src/uu/basename/src/basename.rs index 68b705d53..c20561b30 100644 --- a/src/uu/basename/src/basename.rs +++ b/src/uu/basename/src/basename.rs @@ -10,83 +10,106 @@ #[macro_use] extern crate uucore; +use clap::{App, Arg}; use std::path::{is_separator, PathBuf}; use uucore::InvalidEncodingHandling; -static NAME: &str = "basename"; -static SYNTAX: &str = "NAME [SUFFIX]"; +static VERSION: &str = env!("CARGO_PKG_VERSION"); static SUMMARY: &str = "Print NAME with any leading directory components removed - If specified, also remove a trailing SUFFIX"; -static LONG_HELP: &str = ""; +If specified, also remove a trailing SUFFIX"; + +fn get_usage() -> String { + format!( + "{0} NAME [SUFFIX] + {0} OPTION... NAME...", + executable!() + ) +} + +pub mod options { + pub static MULTIPLE: &str = "multiple"; + pub static NAME: &str = "name"; + pub static SUFFIX: &str = "suffix"; + pub static ZERO: &str = "zero"; +} pub fn uumain(args: impl uucore::Args) -> i32 { let args = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); + let usage = get_usage(); // // Argument parsing // - let matches = app!(SYNTAX, SUMMARY, LONG_HELP) - .optflag( - "a", - "multiple", - "Support more than one argument. Treat every argument as a name.", + let matches = App::new(executable!()) + .version(VERSION) + .about(SUMMARY) + .usage(&usage[..]) + .arg( + Arg::with_name(options::MULTIPLE) + .short("a") + .long(options::MULTIPLE) + .help("support multiple arguments and treat each as a NAME"), ) - .optopt( - "s", - "suffix", - "Remove a trailing suffix. This option implies the -a option.", - "SUFFIX", + .arg(Arg::with_name(options::NAME).multiple(true).hidden(true)) + .arg( + Arg::with_name(options::SUFFIX) + .short("s") + .long(options::SUFFIX) + .value_name("SUFFIX") + .help("remove a trailing SUFFIX; implies -a"), ) - .optflag( - "z", - "zero", - "Output a zero byte (ASCII NUL) at the end of each line, rather than a newline.", + .arg( + Arg::with_name(options::ZERO) + .short("z") + .long(options::ZERO) + .help("end each output line with NUL, not newline"), ) - .parse(args); + .get_matches_from(args); // too few arguments - if matches.free.is_empty() { + if !matches.is_present(options::NAME) { crash!( 1, - "{0}: {1}\nTry '{0} --help' for more information.", - NAME, + "{1}\nTry '{0} --help' for more information.", + executable!(), "missing operand" ); } - let opt_s = matches.opt_present("s"); - let opt_a = matches.opt_present("a"); - let opt_z = matches.opt_present("z"); - let multiple_paths = opt_s || opt_a; + + let opt_suffix = matches.is_present(options::SUFFIX); + let opt_multiple = matches.is_present(options::MULTIPLE); + let opt_zero = matches.is_present(options::ZERO); + let multiple_paths = opt_suffix || opt_multiple; // too many arguments - if !multiple_paths && matches.free.len() > 2 { + if !multiple_paths && matches.occurrences_of(options::NAME) > 2 { crash!( 1, - "{0}: extra operand '{1}'\nTry '{0} --help' for more information.", - NAME, - matches.free[2] + "extra operand '{1}'\nTry '{0} --help' for more information.", + executable!(), + matches.values_of(options::NAME).unwrap().nth(2).unwrap() ); } - let suffix = if opt_s { - matches.opt_str("s").unwrap() - } else if !opt_a && matches.free.len() > 1 { - matches.free[1].clone() + let suffix = if opt_suffix { + matches.value_of(options::SUFFIX).unwrap() + } else if !opt_multiple && matches.occurrences_of(options::NAME) > 1 { + matches.values_of(options::NAME).unwrap().nth(1).unwrap() } else { - "".to_owned() + "" }; // // Main Program Processing // - let paths = if multiple_paths { - &matches.free[..] + let paths: Vec<_> = if multiple_paths { + matches.values_of(options::NAME).unwrap().collect() } else { - &matches.free[0..1] + matches.values_of(options::NAME).unwrap().take(1).collect() }; - let line_ending = if opt_z { "\0" } else { "\n" }; + let line_ending = if opt_zero { "\0" } else { "\n" }; for path in paths { print!("{}{}", basename(&path, &suffix), line_ending); } diff --git a/src/uu/cat/src/splice.rs b/src/uu/cat/src/splice.rs index ccc625467..bd6be60f1 100644 --- a/src/uu/cat/src/splice.rs +++ b/src/uu/cat/src/splice.rs @@ -81,7 +81,7 @@ fn copy_exact(read_fd: RawFd, write_fd: RawFd, num_bytes: usize) -> nix::Result< let mut buf = [0; BUF_SIZE]; loop { let read = unistd::read(read_fd, &mut buf[..left])?; - let written = unistd::write(write_fd, &mut buf[..read])?; + let written = unistd::write(write_fd, &buf[..read])?; left -= written; if left == 0 { break; diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index ca564e37c..3d6faf66a 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -551,6 +551,10 @@ impl FromStr for Attribute { fn add_all_attributes() -> Vec { use Attribute::*; + #[cfg(target_os = "windows")] + let attr = vec![Ownership, Timestamps, Context, Xattr, Links]; + + #[cfg(not(target_os = "windows"))] let mut attr = vec![Ownership, Timestamps, Context, Xattr, Links]; #[cfg(unix)] diff --git a/src/uu/cut/BENCHMARKING.md b/src/uu/cut/BENCHMARKING.md new file mode 100644 index 000000000..bd94cf93c --- /dev/null +++ b/src/uu/cut/BENCHMARKING.md @@ -0,0 +1,46 @@ +## Benchmarking cut + +### Performance profile + +In normal use cases a significant amount of the total execution time of `cut` +is spent performing I/O. When invoked with the `-f` option (cut fields) some +CPU time is spent on detecting fields (in `Searcher::next`). Other than that +some small amount of CPU time is spent on breaking the input stream into lines. + + +### How to + +When fixing bugs or adding features you might want to compare +performance before and after your code changes. + +- `hyperfine` can be used to accurately measure and compare the total + execution time of one or more commands. + + ``` + $ cargo build --release --package uu_cut + + $ hyperfine -w3 "./target/release/cut -f2-4,8 -d' ' input.txt" "cut -f2-4,8 -d' ' input.txt" + ``` + You can put those two commands in a shell script to be sure that you don't + forget to build after making any changes. + +When optimizing or fixing performance regressions seeing the number of times a +function is called, and the amount of time it takes can be useful. + +- `cargo flamegraph` generates flame graphs from function level metrics it records using `perf` or `dtrace` + + ``` + $ cargo flamegraph --bin cut --package uu_cut -- -f1,3-4 input.txt > /dev/null + ``` + + +### What to benchmark + +There are four different performance paths in `cut` to benchmark. + +- Byte ranges `-c`/`--characters` or `-b`/`--bytes` e.g. `cut -c 2,4,6-` +- Byte ranges with output delimiters e.g. `cut -c 4- --output-delimiter=/` +- Fields e.g. `cut -f -4` +- Fields with output delimiters e.g. `cut -f 7-10 --output-delimiter=:` + +Choose a test input file with large number of lines so that program startup time does not significantly affect the benchmark. diff --git a/src/uu/cut/Cargo.toml b/src/uu/cut/Cargo.toml index d892ddeb5..c863c1772 100644 --- a/src/uu/cut/Cargo.toml +++ b/src/uu/cut/Cargo.toml @@ -18,6 +18,8 @@ path = "src/cut.rs" clap = "2.33" uucore = { version=">=0.0.8", package="uucore", path="../../uucore" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +memchr = "2" +bstr = "0.2" [[bin]] name = "cut" diff --git a/src/uu/cut/src/buffer.rs b/src/uu/cut/src/buffer.rs deleted file mode 100644 index 6c3238be1..000000000 --- a/src/uu/cut/src/buffer.rs +++ /dev/null @@ -1,152 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// (c) Rolf Morel -// (c) kwantam -// * substantial rewrite to use the `std::io::BufReader` trait -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -// spell-checker:ignore (ToDO) SRes Newl - -use std::io::Result as IoResult; -use std::io::{BufRead, BufReader, Read, Write}; - -#[allow(non_snake_case)] -pub mod Bytes { - use std::io::Write; - - pub trait Select { - fn select(&mut self, bytes: usize, out: Option<&mut W>) -> Selected; - } - - #[derive(PartialEq, Eq, Debug)] - pub enum Selected { - NewlineFound, - Complete(usize), - Partial(usize), - EndOfFile, - } -} - -#[derive(Debug)] -pub struct ByteReader -where - R: Read, -{ - inner: BufReader, - newline_char: u8, -} - -impl ByteReader { - pub fn new(read: R, newline_char: u8) -> ByteReader { - ByteReader { - inner: BufReader::with_capacity(4096, read), - newline_char, - } - } -} - -impl Read for ByteReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { - self.inner.read(buf) - } -} - -impl BufRead for ByteReader { - fn fill_buf(&mut self) -> IoResult<&[u8]> { - self.inner.fill_buf() - } - - fn consume(&mut self, amt: usize) { - self.inner.consume(amt) - } -} - -impl ByteReader { - pub fn consume_line(&mut self) -> usize { - let mut bytes_consumed = 0; - let mut consume_val; - let newline_char = self.newline_char; - - loop { - { - // need filled_buf to go out of scope - let filled_buf = match self.fill_buf() { - Ok(b) => { - if b.is_empty() { - return bytes_consumed; - } else { - b - } - } - Err(e) => crash!(1, "read error: {}", e), - }; - - if let Some(idx) = filled_buf.iter().position(|byte| *byte == newline_char) { - consume_val = idx + 1; - bytes_consumed += consume_val; - break; - } - - consume_val = filled_buf.len(); - } - - bytes_consumed += consume_val; - self.consume(consume_val); - } - - self.consume(consume_val); - bytes_consumed - } -} - -impl self::Bytes::Select for ByteReader { - fn select(&mut self, bytes: usize, out: Option<&mut W>) -> Bytes::Selected { - enum SRes { - Comp, - Part, - Newl, - } - - use self::Bytes::Selected::*; - - let newline_char = self.newline_char; - let (res, consume_val) = { - let buffer = match self.fill_buf() { - Err(e) => crash!(1, "read error: {}", e), - Ok(b) => b, - }; - - let (res, consume_val) = match buffer.len() { - 0 => return EndOfFile, - buf_used if bytes < buf_used => { - // because the output delimiter should only be placed between - // segments check if the byte after bytes is a newline - let buf_slice = &buffer[0..=bytes]; - - match buf_slice.iter().position(|byte| *byte == newline_char) { - Some(idx) => (SRes::Newl, idx + 1), - None => (SRes::Comp, bytes), - } - } - _ => match buffer.iter().position(|byte| *byte == newline_char) { - Some(idx) => (SRes::Newl, idx + 1), - None => (SRes::Part, buffer.len()), - }, - }; - - if let Some(out) = out { - crash_if_err!(1, out.write_all(&buffer[0..consume_val])); - } - (res, consume_val) - }; - - self.consume(consume_val); - match res { - SRes::Comp => Complete(consume_val), - SRes::Part => Partial(consume_val), - SRes::Newl => NewlineFound, - } - } -} diff --git a/src/uu/cut/src/cut.rs b/src/uu/cut/src/cut.rs index 71c52601e..535027237 100644 --- a/src/uu/cut/src/cut.rs +++ b/src/uu/cut/src/cut.rs @@ -10,16 +10,17 @@ #[macro_use] extern crate uucore; +use bstr::io::BufReadExt; use clap::{App, Arg}; use std::fs::File; -use std::io::{stdin, stdout, BufRead, BufReader, Read, Stdout, Write}; +use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write}; use std::path::Path; use self::searcher::Searcher; +use uucore::fs::is_stdout_interactive; use uucore::ranges::Range; use uucore::InvalidEncodingHandling; -mod buffer; mod searcher; static NAME: &str = "cut"; @@ -126,6 +127,14 @@ enum Mode { Fields(Vec, FieldOptions), } +fn stdout_writer() -> Box { + if is_stdout_interactive() { + Box::new(stdout()) + } else { + Box::new(BufWriter::new(stdout())) as Box + } +} + fn list_to_ranges(list: &str, complement: bool) -> Result, String> { if complement { Range::from_list(list).map(|r| uucore::ranges::complement(&r)) @@ -135,72 +144,35 @@ fn list_to_ranges(list: &str, complement: bool) -> Result, String> { } fn cut_bytes(reader: R, ranges: &[Range], opts: &Options) -> i32 { - use self::buffer::Bytes::Select; - use self::buffer::Bytes::Selected::*; - let newline_char = if opts.zero_terminated { b'\0' } else { b'\n' }; - let mut buf_read = buffer::ByteReader::new(reader, newline_char); - let mut out = stdout(); + let buf_in = BufReader::new(reader); + let mut out = stdout_writer(); + let delim = opts + .out_delim + .as_ref() + .map_or("", String::as_str) + .as_bytes(); - 'newline: loop { - let mut cur_pos = 1; + let res = buf_in.for_byte_record(newline_char, |line| { let mut print_delim = false; - - for &Range { low, high } in ranges.iter() { - // skip up to low - let orig_pos = cur_pos; - loop { - match buf_read.select(low - cur_pos, None::<&mut Stdout>) { - NewlineFound => { - crash_if_err!(1, out.write_all(&[newline_char])); - continue 'newline; - } - Complete(len) => { - cur_pos += len; - break; - } - Partial(len) => cur_pos += len, - EndOfFile => { - if orig_pos != cur_pos { - crash_if_err!(1, out.write_all(&[newline_char])); - } - - break 'newline; - } - } + for &Range { low, high } in ranges { + if low > line.len() { + break; } - - if let Some(ref delim) = opts.out_delim { - if print_delim { - crash_if_err!(1, out.write_all(delim.as_bytes())); - } + if print_delim { + out.write_all(delim)?; + } else if opts.out_delim.is_some() { print_delim = true; } - - // write out from low to high - loop { - match buf_read.select(high - cur_pos + 1, Some(&mut out)) { - NewlineFound => continue 'newline, - Partial(len) => cur_pos += len, - Complete(_) => { - cur_pos = high + 1; - break; - } - EndOfFile => { - if cur_pos != low || low == high { - crash_if_err!(1, out.write_all(&[newline_char])); - } - - break 'newline; - } - } - } + // change `low` from 1-indexed value to 0-index value + let low = low - 1; + let high = high.min(line.len()); + out.write_all(&line[low..high])?; } - - buf_read.consume_line(); - crash_if_err!(1, out.write_all(&[newline_char])); - } - + out.write_all(&[newline_char])?; + Ok(true) + }); + crash_if_err!(1, res); 0 } @@ -213,23 +185,11 @@ fn cut_fields_delimiter( newline_char: u8, out_delim: &str, ) -> i32 { - let mut buf_in = BufReader::new(reader); - let mut out = stdout(); - let mut buffer = Vec::new(); + let buf_in = BufReader::new(reader); + let mut out = stdout_writer(); + let input_delim_len = delim.len(); - 'newline: loop { - buffer.clear(); - match buf_in.read_until(newline_char, &mut buffer) { - Ok(n) if n == 0 => break, - Err(e) => { - if buffer.is_empty() { - crash!(1, "read error: {}", e); - } - } - _ => (), - } - - let line = &buffer[..]; + let result = buf_in.for_byte_record_with_terminator(newline_char, |line| { let mut fields_pos = 1; let mut low_idx = 0; let mut delim_search = Searcher::new(line, delim.as_bytes()).peekable(); @@ -237,46 +197,46 @@ fn cut_fields_delimiter( if delim_search.peek().is_none() { if !only_delimited { - crash_if_err!(1, out.write_all(line)); + out.write_all(line)?; if line[line.len() - 1] != newline_char { - crash_if_err!(1, out.write_all(&[newline_char])); + out.write_all(&[newline_char])?; } } - continue; + return Ok(true); } - for &Range { low, high } in ranges.iter() { + for &Range { low, high } in ranges { if low - fields_pos > 0 { low_idx = match delim_search.nth(low - fields_pos - 1) { - Some((_, beyond_delim)) => beyond_delim, + Some(index) => index + input_delim_len, None => break, }; } for _ in 0..=high - low { if print_delim { - crash_if_err!(1, out.write_all(out_delim.as_bytes())); + out.write_all(out_delim.as_bytes())?; + } else { + print_delim = true; } match delim_search.next() { - Some((high_idx, next_low_idx)) => { + Some(high_idx) => { let segment = &line[low_idx..high_idx]; - crash_if_err!(1, out.write_all(segment)); + out.write_all(segment)?; - print_delim = true; - - low_idx = next_low_idx; + low_idx = high_idx + input_delim_len; fields_pos = high + 1; } None => { let segment = &line[low_idx..]; - crash_if_err!(1, out.write_all(segment)); + out.write_all(segment)?; if line[line.len() - 1] == newline_char { - continue 'newline; + return Ok(true); } break; } @@ -284,9 +244,10 @@ fn cut_fields_delimiter( } } - crash_if_err!(1, out.write_all(&[newline_char])); - } - + out.write_all(&[newline_char])?; + Ok(true) + }); + crash_if_err!(1, result); 0 } @@ -304,23 +265,11 @@ fn cut_fields(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32 ); } - let mut buf_in = BufReader::new(reader); - let mut out = stdout(); - let mut buffer = Vec::new(); + let buf_in = BufReader::new(reader); + let mut out = stdout_writer(); + let delim_len = opts.delimiter.len(); - 'newline: loop { - buffer.clear(); - match buf_in.read_until(newline_char, &mut buffer) { - Ok(n) if n == 0 => break, - Err(e) => { - if buffer.is_empty() { - crash!(1, "read error: {}", e); - } - } - _ => (), - } - - let line = &buffer[..]; + let result = buf_in.for_byte_record_with_terminator(newline_char, |line| { let mut fields_pos = 1; let mut low_idx = 0; let mut delim_search = Searcher::new(line, opts.delimiter.as_bytes()).peekable(); @@ -328,53 +277,54 @@ fn cut_fields(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32 if delim_search.peek().is_none() { if !opts.only_delimited { - crash_if_err!(1, out.write_all(line)); + out.write_all(line)?; if line[line.len() - 1] != newline_char { - crash_if_err!(1, out.write_all(&[newline_char])); + out.write_all(&[newline_char])?; } } - continue; + return Ok(true); } - for &Range { low, high } in ranges.iter() { + for &Range { low, high } in ranges { if low - fields_pos > 0 { - low_idx = match delim_search.nth(low - fields_pos - 1) { - Some((_, beyond_delim)) => beyond_delim, - None => break, - }; - } - - if print_delim && low_idx >= opts.delimiter.as_bytes().len() { - low_idx -= opts.delimiter.as_bytes().len(); + if let Some(delim_pos) = delim_search.nth(low - fields_pos - 1) { + low_idx = if print_delim { + delim_pos + } else { + delim_pos + delim_len + } + } else { + break; + } } match delim_search.nth(high - low) { - Some((high_idx, next_low_idx)) => { + Some(high_idx) => { let segment = &line[low_idx..high_idx]; - crash_if_err!(1, out.write_all(segment)); + out.write_all(segment)?; print_delim = true; - low_idx = next_low_idx; + low_idx = high_idx; fields_pos = high + 1; } None => { let segment = &line[low_idx..line.len()]; - crash_if_err!(1, out.write_all(segment)); + out.write_all(segment)?; if line[line.len() - 1] == newline_char { - continue 'newline; + return Ok(true); } break; } } } - - crash_if_err!(1, out.write_all(&[newline_char])); - } - + out.write_all(&[newline_char])?; + Ok(true) + }); + crash_if_err!(1, result); 0 } diff --git a/src/uu/cut/src/searcher.rs b/src/uu/cut/src/searcher.rs index f0821ff3a..5fe4a723b 100644 --- a/src/uu/cut/src/searcher.rs +++ b/src/uu/cut/src/searcher.rs @@ -5,7 +5,8 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -#[derive(Clone)] +use memchr::memchr; + pub struct Searcher<'a> { haystack: &'a [u8], needle: &'a [u8], @@ -14,6 +15,7 @@ pub struct Searcher<'a> { impl<'a> Searcher<'a> { pub fn new(haystack: &'a [u8], needle: &'a [u8]) -> Searcher<'a> { + assert!(!needle.is_empty()); Searcher { haystack, needle, @@ -23,30 +25,81 @@ impl<'a> Searcher<'a> { } impl<'a> Iterator for Searcher<'a> { - type Item = (usize, usize); + type Item = usize; - fn next(&mut self) -> Option<(usize, usize)> { - if self.needle.len() == 1 { - for offset in self.position..self.haystack.len() { - if self.haystack[offset] == self.needle[0] { - self.position = offset + 1; - return Some((offset, offset + 1)); + fn next(&mut self) -> Option { + loop { + if let Some(match_idx) = memchr(self.needle[0], self.haystack) { + if self.needle.len() == 1 + || self.haystack[match_idx + 1..].starts_with(&self.needle[1..]) + { + let match_pos = self.position + match_idx; + let skip = match_idx + self.needle.len(); + self.haystack = &self.haystack[skip..]; + self.position += skip; + return Some(match_pos); + } else { + let skip = match_idx + 1; + self.haystack = &self.haystack[skip..]; + self.position += skip; + // continue } - } - - self.position = self.haystack.len(); - return None; - } - - while self.position + self.needle.len() <= self.haystack.len() { - if &self.haystack[self.position..self.position + self.needle.len()] == self.needle { - let match_pos = self.position; - self.position += self.needle.len(); - return Some((match_pos, match_pos + self.needle.len())); } else { - self.position += 1; + return None; } } - None + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + const NEEDLE: &[u8] = "ab".as_bytes(); + + #[test] + fn test_normal() { + let iter = Searcher::new("a.a.a".as_bytes(), "a".as_bytes()); + let items: Vec = iter.collect(); + assert_eq!(vec![0, 2, 4], items); + } + + #[test] + fn test_empty() { + let iter = Searcher::new("".as_bytes(), "a".as_bytes()); + let items: Vec = iter.collect(); + assert_eq!(vec![] as Vec, items); + } + + fn test_multibyte(line: &[u8], expected: Vec) { + let iter = Searcher::new(line, NEEDLE); + let items: Vec = iter.collect(); + assert_eq!(expected, items); + } + + #[test] + fn test_multibyte_normal() { + test_multibyte("...ab...ab...".as_bytes(), vec![3, 8]); + } + + #[test] + fn test_multibyte_needle_head_at_end() { + test_multibyte("a".as_bytes(), vec![]); + } + + #[test] + fn test_multibyte_starting_needle() { + test_multibyte("ab...ab...".as_bytes(), vec![0, 5]); + } + + #[test] + fn test_multibyte_trailing_needle() { + test_multibyte("...ab...ab".as_bytes(), vec![3, 8]); + } + + #[test] + fn test_multibyte_first_byte_false_match() { + test_multibyte("aA..aCaC..ab..aD".as_bytes(), vec![10]); } } diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index 43573437d..317fd72d4 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -348,7 +348,7 @@ fn set_system_datetime(_date: DateTime) -> i32 { #[cfg(target_os = "macos")] fn set_system_datetime(_date: DateTime) -> i32 { eprintln!("date: setting the date is not supported by macOS"); - return 1; + 1 } #[cfg(all(unix, not(target_os = "macos")))] diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index e898b187c..c917eb2e8 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -916,6 +916,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 { "Use%", ] }); + if cfg!(target_os = "macos") && !opt.show_inode_instead { + header.insert(header.len() - 1, "Capacity"); + } header.push("Mounted on"); for (idx, title) in header.iter().enumerate() { @@ -970,6 +973,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 { "{0: >12} ", human_readable(free_size, opt.human_readable_base) ); + if cfg!(target_os = "macos") { + let used = fs.usage.blocks - fs.usage.bfree; + let blocks = used + fs.usage.bavail; + print!("{0: >12} ", use_size(used, blocks)); + } print!("{0: >5} ", use_size(free_size, total_size)); } print!("{0: <16}", fs.mountinfo.mount_dir); diff --git a/src/uu/dirname/src/dirname.rs b/src/uu/dirname/src/dirname.rs index 5937f16ca..63693c982 100644 --- a/src/uu/dirname/src/dirname.rs +++ b/src/uu/dirname/src/dirname.rs @@ -12,37 +12,42 @@ use clap::{App, Arg}; use std::path::Path; use uucore::InvalidEncodingHandling; -static NAME: &str = "dirname"; -static SYNTAX: &str = "[OPTION] NAME..."; -static SUMMARY: &str = "strip last component from file name"; +static ABOUT: &str = "strip last component from file name"; static VERSION: &str = env!("CARGO_PKG_VERSION"); -static LONG_HELP: &str = " - Output each NAME with its last non-slash component and trailing slashes - removed; if NAME contains no /'s, output '.' (meaning the current - directory). -"; mod options { pub const ZERO: &str = "zero"; pub const DIR: &str = "dir"; } +fn get_usage() -> String { + format!("{0} [OPTION] NAME...", executable!()) +} + +fn get_long_usage() -> String { + String::from( + "Output each NAME with its last non-slash component and trailing slashes + removed; if NAME contains no /'s, output '.' (meaning the current directory).", + ) +} + pub fn uumain(args: impl uucore::Args) -> i32 { let args = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); + let usage = get_usage(); + let after_help = get_long_usage(); + let matches = App::new(executable!()) - .name(NAME) - .usage(SYNTAX) - .about(SUMMARY) - .after_help(LONG_HELP) + .about(ABOUT) + .usage(&usage[..]) + .after_help(&after_help[..]) .version(VERSION) .arg( Arg::with_name(options::ZERO) - .short(options::ZERO) + .long(options::ZERO) .short("z") - .takes_value(false) .help("separate output with NUL rather than newline"), ) .arg(Arg::with_name(options::DIR).hidden(true).multiple(true)) diff --git a/src/uu/factor/Cargo.toml b/src/uu/factor/Cargo.toml index 489c713be..c4e7e8469 100644 --- a/src/uu/factor/Cargo.toml +++ b/src/uu/factor/Cargo.toml @@ -14,8 +14,8 @@ edition = "2018" [build-dependencies] num-traits = "0.2.13" # used in src/numerics.rs, which is included by build.rs - [dependencies] +coz = { version = "0.1.3", optional = true } num-traits = "0.2.13" # Needs at least version 0.2.13 for "OverflowingAdd" rand = { version="0.7", features=["small_rng"] } smallvec = { version="0.6.14, < 1.0" } diff --git a/src/uu/factor/src/factor.rs b/src/uu/factor/src/factor.rs index 7d2e16a11..138254b51 100644 --- a/src/uu/factor/src/factor.rs +++ b/src/uu/factor/src/factor.rs @@ -125,6 +125,8 @@ fn _factor(num: u64, f: Factors) -> Factors let n = A::new(num); let divisor = match miller_rabin::test::(n) { Prime => { + #[cfg(feature = "coz")] + coz::progress!("factor found"); let mut r = f; r.push(num); return r; @@ -139,6 +141,8 @@ fn _factor(num: u64, f: Factors) -> Factors } pub fn factor(mut n: u64) -> Factors { + #[cfg(feature = "coz")] + coz::begin!("factorization"); let mut factors = Factors::one(); if n < 2 { @@ -152,16 +156,23 @@ pub fn factor(mut n: u64) -> Factors { } if n == 1 { + #[cfg(feature = "coz")] + coz::end!("factorization"); return factors; } let (factors, n) = table::factor(n, factors); - if n < (1 << 32) { + let r = if n < (1 << 32) { _factor::>(n, factors) } else { _factor::>(n, factors) - } + }; + + #[cfg(feature = "coz")] + coz::end!("factorization"); + + r } #[cfg(test)] diff --git a/src/uu/factor/src/table.rs b/src/uu/factor/src/table.rs index d6ef796fc..94ad6df4c 100644 --- a/src/uu/factor/src/table.rs +++ b/src/uu/factor/src/table.rs @@ -33,6 +33,8 @@ pub(crate) fn factor(mut num: u64, mut factors: Factors) -> (Factors, u64) { if x <= ceil { num = x; k += 1; + #[cfg(feature = "coz")] + coz::progress!("factor found"); } else { if k > 0 { factors.add(prime, k); diff --git a/src/uu/kill/Cargo.toml b/src/uu/kill/Cargo.toml index 6b66806bc..e33411c70 100644 --- a/src/uu/kill/Cargo.toml +++ b/src/uu/kill/Cargo.toml @@ -15,6 +15,7 @@ edition = "2018" path = "src/kill.rs" [dependencies] +clap = "2.33" libc = "0.2.42" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["signals"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/kill/src/kill.rs b/src/uu/kill/src/kill.rs index 916c13cc3..362f13f18 100644 --- a/src/uu/kill/src/kill.rs +++ b/src/uu/kill/src/kill.rs @@ -10,18 +10,26 @@ #[macro_use] extern crate uucore; +use clap::{App, Arg}; use libc::{c_int, pid_t}; use std::io::Error; use uucore::signals::ALL_SIGNALS; use uucore::InvalidEncodingHandling; -static SYNTAX: &str = "[options] [...]"; -static SUMMARY: &str = ""; -static LONG_HELP: &str = ""; +static VERSION: &str = env!("CARGO_PKG_VERSION"); +static ABOUT: &str = "Send signal to processes or list information about signals."; static EXIT_OK: i32 = 0; static EXIT_ERR: i32 = 1; +pub mod options { + pub static PIDS_OR_SIGNALS: &str = "pids_of_signals"; + pub static LIST: &str = "list"; + pub static TABLE: &str = "table"; + pub static TABLE_OLD: &str = "table_old"; + pub static SIGNAL: &str = "signal"; +} + #[derive(Clone, Copy)] pub enum Mode { Kill, @@ -33,41 +41,70 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let args = args .collect_str(InvalidEncodingHandling::Ignore) .accept_any(); - let (args, obs_signal) = handle_obsolete(args); - let matches = app!(SYNTAX, SUMMARY, LONG_HELP) - .optopt("s", "signal", "specify the to be sent", "SIGNAL") - .optflagopt( - "l", - "list", - "list all signal names, or convert one to a name", - "LIST", - ) - .optflag("L", "table", "list all signal names in a nice table") - .parse(args); - let mode = if matches.opt_present("table") { + let usage = format!("{} [OPTIONS]... PID...", executable!()); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .arg( + Arg::with_name(options::LIST) + .short("l") + .long(options::LIST) + .help("Lists signals") + .conflicts_with(options::TABLE) + .conflicts_with(options::TABLE_OLD), + ) + .arg( + Arg::with_name(options::TABLE) + .short("t") + .long(options::TABLE) + .help("Lists table of signals"), + ) + .arg(Arg::with_name(options::TABLE_OLD).short("L").hidden(true)) + .arg( + Arg::with_name(options::SIGNAL) + .short("s") + .long(options::SIGNAL) + .help("Sends given signal") + .takes_value(true), + ) + .arg( + Arg::with_name(options::PIDS_OR_SIGNALS) + .hidden(true) + .multiple(true), + ) + .get_matches_from(args); + + let mode = if matches.is_present(options::TABLE) || matches.is_present(options::TABLE_OLD) { Mode::Table - } else if matches.opt_present("list") { + } else if matches.is_present(options::LIST) { Mode::List } else { Mode::Kill }; + let pids_or_signals: Vec = matches + .values_of(options::PIDS_OR_SIGNALS) + .map(|v| v.map(ToString::to_string).collect()) + .unwrap_or_default(); + match mode { Mode::Kill => { - return kill( - &matches - .opt_str("signal") - .unwrap_or_else(|| obs_signal.unwrap_or_else(|| "9".to_owned())), - matches.free, - ) + let sig = match (obs_signal, matches.value_of(options::SIGNAL)) { + (Some(s), Some(_)) => s, // -s takes precedence + (Some(s), None) => s, + (None, Some(s)) => s.to_owned(), + (None, None) => "TERM".to_owned(), + }; + return kill(&sig, &pids_or_signals); } Mode::Table => table(), - Mode::List => list(matches.opt_str("list")), + Mode::List => list(pids_or_signals.get(0).cloned()), } - 0 + EXIT_OK } fn handle_obsolete(mut args: Vec) -> (Vec, Option) { @@ -148,14 +185,14 @@ fn list(arg: Option) { }; } -fn kill(signalname: &str, pids: std::vec::Vec) -> i32 { +fn kill(signalname: &str, pids: &[String]) -> i32 { let mut status = 0; let optional_signal_value = uucore::signals::signal_by_name_or_value(signalname); let signal_value = match optional_signal_value { Some(x) => x, None => crash!(EXIT_ERR, "unknown signal name {}", signalname), }; - for pid in &pids { + for pid in pids { match pid.parse::() { Ok(x) => { if unsafe { libc::kill(x as pid_t, signal_value as c_int) } != 0 { diff --git a/src/uu/link/Cargo.toml b/src/uu/link/Cargo.toml index 13c3453cf..14a6ac7c9 100644 --- a/src/uu/link/Cargo.toml +++ b/src/uu/link/Cargo.toml @@ -18,6 +18,7 @@ path = "src/link.rs" libc = "0.2.42" uucore = { version=">=0.0.8", package="uucore", path="../../uucore" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +clap = "2.33" [[bin]] name = "link" diff --git a/src/uu/link/src/link.rs b/src/uu/link/src/link.rs index b82d7cfac..bd8b33355 100644 --- a/src/uu/link/src/link.rs +++ b/src/uu/link/src/link.rs @@ -8,14 +8,21 @@ #[macro_use] extern crate uucore; +use clap::{App, Arg}; use std::fs::hard_link; use std::io::Error; use std::path::Path; -use uucore::InvalidEncodingHandling; -static SYNTAX: &str = "[OPTIONS] FILE1 FILE2"; -static SUMMARY: &str = "Create a link named FILE2 to FILE1"; -static LONG_HELP: &str = ""; +static VERSION: &str = env!("CARGO_PKG_VERSION"); +static ABOUT: &str = "Call the link function to create a link named FILE2 to an existing FILE1."; + +pub mod options { + pub static FILES: &str = "FILES"; +} + +fn get_usage() -> String { + format!("{0} FILE1 FILE2", executable!()) +} pub fn normalize_error_message(e: Error) -> String { match e.raw_os_error() { @@ -25,16 +32,27 @@ pub fn normalize_error_message(e: Error) -> String { } pub fn uumain(args: impl uucore::Args) -> i32 { - let matches = app!(SYNTAX, SUMMARY, LONG_HELP).parse( - args.collect_str(InvalidEncodingHandling::Ignore) - .accept_any(), - ); - if matches.free.len() != 2 { - crash!(1, "{}", msg_wrong_number_of_arguments!(2)); - } + let usage = get_usage(); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .arg( + Arg::with_name(options::FILES) + .hidden(true) + .required(true) + .min_values(2) + .max_values(2) + .takes_value(true), + ) + .get_matches_from(args); - let old = Path::new(&matches.free[0]); - let new = Path::new(&matches.free[1]); + let files: Vec<_> = matches + .values_of_os(options::FILES) + .unwrap_or_default() + .collect(); + let old = Path::new(files[0]); + let new = Path::new(files[1]); match hard_link(old, new) { Ok(_) => 0, diff --git a/src/uu/ls/BENCHMARKING.md b/src/uu/ls/BENCHMARKING.md index 852220496..b009b703a 100644 --- a/src/uu/ls/BENCHMARKING.md +++ b/src/uu/ls/BENCHMARKING.md @@ -36,6 +36,8 @@ args="$@" hyperfine "ls $args" "target/release/coreutils ls $args" ``` +**Note**: No localization is currently implemented. This means that the comparison above is not really fair. We can fix this by setting `LC_ALL=C`, so GNU `ls` can ignore localization. + ## Checking system call count - Another thing to look at would be system calls count using strace (on linux) or equivalent on other operating systems. diff --git a/src/uu/ls/Cargo.toml b/src/uu/ls/Cargo.toml index d479a57f4..ab58a7300 100644 --- a/src/uu/ls/Cargo.toml +++ b/src/uu/ls/Cargo.toml @@ -15,16 +15,17 @@ edition = "2018" path = "src/ls.rs" [dependencies] +locale = "0.2.2" +chrono = "0.4.19" clap = "2.33" unicode-width = "0.1.8" number_prefix = "0.4" term_grid = "0.1.5" termsize = "0.1.6" -time = "0.1.40" globset = "0.4.6" -lscolors = { version="0.7.1", features=["ansi_term"] } -uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["entries", "fs"] } -uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +lscolors = { version = "0.7.1", features = ["ansi_term"] } +uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore", features = ["entries", "fs"] } +uucore_procs = { version = ">=0.0.5", package = "uucore_procs", path = "../../uucore_procs" } once_cell = "1.7.2" atty = "0.2" diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 3245e2a56..0e2754f07 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -38,8 +38,9 @@ use std::{ os::unix::fs::{FileTypeExt, MetadataExt}, time::Duration, }; + use term_grid::{Cell, Direction, Filling, Grid, GridOptions}; -use time::{strftime, Timespec}; + use unicode_width::UnicodeWidthStr; #[cfg(unix)] use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR}; @@ -50,6 +51,8 @@ static ABOUT: &str = " the command line, expect that it will ignore files and directories whose names start with '.' "; +static AFTER_HELP: &str = "The TIME_STYLE argument can be full-iso, long-iso, iso. +Also the TIME_STYLE environment variable sets the default style to use."; fn get_usage() -> String { format!("{0} [OPTION]... [FILE]...", executable!()) @@ -117,6 +120,8 @@ pub mod options { pub static COLOR: &str = "color"; pub static PATHS: &str = "paths"; pub static INDICATOR_STYLE: &str = "indicator-style"; + pub static TIME_STYLE: &str = "time-style"; + pub static FULL_TIME: &str = "full-time"; pub static HIDE: &str = "hide"; pub static IGNORE: &str = "ignore"; } @@ -156,6 +161,15 @@ enum Time { Modification, Access, Change, + Birth, +} + +#[derive(Debug)] +enum TimeStyle { + FullIso, + LongIso, + Iso, + Locale, } enum Dereference { @@ -191,6 +205,7 @@ struct Config { width: Option, quoting_style: QuotingStyle, indicator_style: IndicatorStyle, + time_style: TimeStyle, } // Fields that can be removed or added to the long format @@ -251,6 +266,7 @@ impl Config { options::format::LONG_NO_OWNER, options::format::LONG_NO_GROUP, options::format::LONG_NUMERIC_UID_GID, + options::FULL_TIME, ] .iter() .flat_map(|opt| options.indices_of(opt)) @@ -302,6 +318,7 @@ impl Config { match field { "ctime" | "status" => Time::Change, "access" | "atime" | "use" => Time::Access, + "birth" | "creation" => Time::Birth, // below should never happen as clap already restricts the values. _ => unreachable!("Invalid field for --time"), } @@ -439,6 +456,30 @@ impl Config { IndicatorStyle::None }; + let time_style = if let Some(field) = options.value_of(options::TIME_STYLE) { + //If both FULL_TIME and TIME_STYLE are present + //The one added last is dominant + if options.is_present(options::FULL_TIME) + && options.indices_of(options::FULL_TIME).unwrap().last() + > options.indices_of(options::TIME_STYLE).unwrap().last() + { + TimeStyle::FullIso + } else { + //Clap handles the env variable "TIME_STYLE" + match field { + "full-iso" => TimeStyle::FullIso, + "long-iso" => TimeStyle::LongIso, + "iso" => TimeStyle::Iso, + "locale" => TimeStyle::Locale, + // below should never happen as clap already restricts the values. + _ => unreachable!("Invalid field for --time-style"), + } + } + } else if options.is_present(options::FULL_TIME) { + TimeStyle::FullIso + } else { + TimeStyle::Locale + }; let mut ignore_patterns = GlobSetBuilder::new(); if options.is_present(options::IGNORE_BACKUPS) { ignore_patterns.add(Glob::new("*~").unwrap()); @@ -504,6 +545,7 @@ impl Config { width, quoting_style, indicator_style, + time_style, } } } @@ -696,10 +738,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .long(options::TIME) .help("Show time in :\n\ \taccess time (-u): atime, access, use;\n\ - \tchange time (-t): ctime, status.") + \tchange time (-t): ctime, status.\n\ + \tbirth time: birth, creation;") .value_name("field") .takes_value(true) - .possible_values(&["atime", "access", "use", "ctime", "status"]) + .possible_values(&["atime", "access", "use", "ctime", "status", "birth", "creation"]) .hide_possible_values(true) .require_equals(true) .overrides_with_all(&[ @@ -1020,9 +1063,34 @@ pub fn uumain(args: impl uucore::Args) -> i32 { options::indicator_style::CLASSIFY, options::INDICATOR_STYLE, ])) + .arg( + //This still needs support for posix-*, +FORMAT + Arg::with_name(options::TIME_STYLE) + .long(options::TIME_STYLE) + .help("time/date format with -l; see TIME_STYLE below") + .value_name("TIME_STYLE") + .env("TIME_STYLE") + .possible_values(&[ + "full-iso", + "long-iso", + "iso", + "locale", + ]) + .overrides_with_all(&[ + options::TIME_STYLE + ]) + ) + .arg( + Arg::with_name(options::FULL_TIME) + .long(options::FULL_TIME) + .overrides_with(options::FULL_TIME) + .help("like -l --time-style=full-iso") + ) // Positional arguments - .arg(Arg::with_name(options::PATHS).multiple(true).takes_value(true)); + .arg(Arg::with_name(options::PATHS).multiple(true).takes_value(true)) + + .after_help(AFTER_HELP); let matches = app.get_matches_from(args); @@ -1052,14 +1120,21 @@ impl PathData { fn new( p_buf: PathBuf, file_type: Option>, + file_name: Option, config: &Config, command_line: bool, ) -> Self { - let name = p_buf - .file_name() - .unwrap_or_else(|| p_buf.iter().next_back().unwrap()) - .to_string_lossy() - .into_owned(); + // We cannot use `Path::ends_with` or `Path::Components`, because they remove occurrences of '.' + // For '..', the filename is None + let name = if let Some(name) = file_name { + name + } else { + p_buf + .file_name() + .unwrap_or_else(|| p_buf.iter().next_back().unwrap()) + .to_string_lossy() + .into_owned() + }; let must_dereference = match &config.dereference { Dereference::All => true, Dereference::Args => command_line, @@ -1122,7 +1197,7 @@ fn list(locs: Vec, config: Config) -> i32 { continue; } - let path_data = PathData::new(p, None, &config, true); + let path_data = PathData::new(p, None, None, &config, true); let show_dir_contents = if let Some(ft) = path_data.file_type() { !config.directory && ft.is_dir() @@ -1167,14 +1242,8 @@ fn sort_entries(entries: &mut Vec, config: &Config) { entries.sort_by_key(|k| Reverse(k.md().as_ref().map(|md| md.len()).unwrap_or(0))) } // The default sort in GNU ls is case insensitive - Sort::Name => entries.sort_by_cached_key(|k| { - let has_dot: bool = k.file_name.starts_with('.'); - let filename_nodot: &str = &k.file_name[if has_dot { 1 } else { 0 }..]; - // We want hidden files to appear before regular files of the same - // name, so we need to negate the "has_dot" variable. - (filename_nodot.to_lowercase(), !has_dot) - }), - Sort::Version => entries.sort_by(|k, j| version_cmp::version_cmp(&k.p_buf, &j.p_buf)), + Sort::Name => entries.sort_by(|a, b| a.file_name.cmp(&b.file_name)), + Sort::Version => entries.sort_by(|a, b| version_cmp::version_cmp(&a.p_buf, &b.p_buf)), Sort::Extension => entries.sort_by(|a, b| { a.p_buf .extension() @@ -1213,8 +1282,14 @@ fn should_display(entry: &DirEntry, config: &Config) -> bool { fn enter_directory(dir: &PathData, config: &Config, out: &mut BufWriter) { let mut entries: Vec<_> = if config.files == Files::All { vec![ - PathData::new(dir.p_buf.join("."), None, config, false), - PathData::new(dir.p_buf.join(".."), None, config, false), + PathData::new( + dir.p_buf.clone(), + Some(Ok(*dir.file_type().unwrap())), + Some(".".into()), + config, + false, + ), + PathData::new(dir.p_buf.join(".."), None, Some("..".into()), config, false), ] } else { vec![] @@ -1223,7 +1298,7 @@ fn enter_directory(dir: &PathData, config: &Config, out: &mut BufWriter) let mut temp: Vec<_> = safe_unwrap!(fs::read_dir(&dir.p_buf)) .map(|res| safe_unwrap!(res)) .filter(|e| should_display(e, config)) - .map(|e| PathData::new(DirEntry::path(&e), Some(e.file_type()), config, false)) + .map(|e| PathData::new(DirEntry::path(&e), Some(e.file_type()), None, config, false)) .collect(); sort_entries(&mut temp, config); @@ -1480,6 +1555,7 @@ fn get_system_time(md: &Metadata, config: &Config) -> Option { Time::Change => Some(UNIX_EPOCH + Duration::new(md.ctime() as u64, md.ctime_nsec() as u32)), Time::Modification => md.modified().ok(), Time::Access => md.accessed().ok(), + Time::Birth => md.created().ok(), } } @@ -1488,22 +1564,40 @@ fn get_system_time(md: &Metadata, config: &Config) -> Option { match config.time { Time::Modification => md.modified().ok(), Time::Access => md.accessed().ok(), + Time::Birth => md.created().ok(), _ => None, } } -fn get_time(md: &Metadata, config: &Config) -> Option { - let duration = get_system_time(md, config)? - .duration_since(UNIX_EPOCH) - .ok()?; - let secs = duration.as_secs() as i64; - let nsec = duration.subsec_nanos() as i32; - Some(time::at(Timespec::new(secs, nsec))) +fn get_time(md: &Metadata, config: &Config) -> Option> { + let time = get_system_time(md, config)?; + Some(time.into()) } fn display_date(metadata: &Metadata, config: &Config) -> String { match get_time(metadata, config) { - Some(time) => strftime("%F %R", &time).unwrap(), + Some(time) => { + //Date is recent if from past 6 months + //According to GNU a Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds on the average. + let recent = time + chrono::Duration::seconds(31556952 / 2) > chrono::Local::now(); + + match config.time_style { + TimeStyle::FullIso => time.format("%Y-%m-%d %H:%M:%S.%f %z"), + TimeStyle::LongIso => time.format("%Y-%m-%d %H:%M"), + TimeStyle::Iso => time.format(if recent { "%m-%d %H:%M" } else { "%Y-%m-%d " }), + TimeStyle::Locale => { + let fmt = if recent { "%b %e %H:%M" } else { "%b %e %Y" }; + + //In this version of chrono translating can be done + //The function is chrono::datetime::DateTime::format_localized + //However it's currently still hard to get the current pure-rust-locale + //So it's not yet implemented + + time.format(fmt) + } + } + .to_string() + } None => "???".into(), } } diff --git a/src/uu/pinky/Cargo.toml b/src/uu/pinky/Cargo.toml index 3f4a75241..a3c36259a 100644 --- a/src/uu/pinky/Cargo.toml +++ b/src/uu/pinky/Cargo.toml @@ -17,6 +17,7 @@ path = "src/pinky.rs" [dependencies] uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["utmpx", "entries"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +clap = "2.33.3" [[bin]] name = "pinky" diff --git a/src/uu/pinky/src/pinky.rs b/src/uu/pinky/src/pinky.rs index a02096bc8..e116a2382 100644 --- a/src/uu/pinky/src/pinky.rs +++ b/src/uu/pinky/src/pinky.rs @@ -19,67 +19,110 @@ use std::io::BufReader; use std::fs::File; use std::os::unix::fs::MetadataExt; +use clap::{App, Arg}; use std::path::PathBuf; use uucore::InvalidEncodingHandling; -static SYNTAX: &str = "[OPTION]... [USER]..."; -static SUMMARY: &str = "A lightweight 'finger' program; print user information."; - const BUFSIZE: usize = 1024; +static VERSION: &str = env!("CARGO_PKG_VERSION"); +static ABOUT: &str = "pinky - lightweight finger"; + +mod options { + pub const LONG_FORMAT: &str = "long_format"; + pub const OMIT_HOME_DIR: &str = "omit_home_dir"; + pub const OMIT_PROJECT_FILE: &str = "omit_project_file"; + pub const OMIT_PLAN_FILE: &str = "omit_plan_file"; + pub const SHORT_FORMAT: &str = "short_format"; + pub const OMIT_HEADINGS: &str = "omit_headings"; + pub const OMIT_NAME: &str = "omit_name"; + pub const OMIT_NAME_HOST: &str = "omit_name_host"; + pub const OMIT_NAME_HOST_TIME: &str = "omit_name_host_time"; + pub const USER: &str = "user"; +} + +fn get_usage() -> String { + format!("{0} [OPTION]... [USER]...", executable!()) +} + +fn get_long_usage() -> String { + format!( + "A lightweight 'finger' program; print user information.\n\ + The utmp file will be {}.", + utmpx::DEFAULT_FILE + ) +} + pub fn uumain(args: impl uucore::Args) -> i32 { let args = args .collect_str(InvalidEncodingHandling::Ignore) .accept_any(); - let long_help = &format!( - " - -l produce long format output for the specified USERs - -b omit the user's home directory and shell in long format - -h omit the user's project file in long format - -p omit the user's plan file in long format - -s do short format output, this is the default - -f omit the line of column headings in short format - -w omit the user's full name in short format - -i omit the user's full name and remote host in short format - -q omit the user's full name, remote host and idle time - in short format - --help display this help and exit - --version output version information and exit + let usage = get_usage(); + let after_help = get_long_usage(); -The utmp file will be {}", - utmpx::DEFAULT_FILE - ); - let mut opts = app!(SYNTAX, SUMMARY, &long_help); - opts.optflag( - "l", - "", - "produce long format output for the specified USERs", - ); - opts.optflag( - "b", - "", - "omit the user's home directory and shell in long format", - ); - opts.optflag("h", "", "omit the user's project file in long format"); - opts.optflag("p", "", "omit the user's plan file in long format"); - opts.optflag("s", "", "do short format output, this is the default"); - opts.optflag("f", "", "omit the line of column headings in short format"); - opts.optflag("w", "", "omit the user's full name in short format"); - opts.optflag( - "i", - "", - "omit the user's full name and remote host in short format", - ); - opts.optflag( - "q", - "", - "omit the user's full name, remote host and idle time in short format", - ); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .after_help(&after_help[..]) + .arg( + Arg::with_name(options::LONG_FORMAT) + .short("l") + .requires(options::USER) + .help("produce long format output for the specified USERs"), + ) + .arg( + Arg::with_name(options::OMIT_HOME_DIR) + .short("b") + .help("omit the user's home directory and shell in long format"), + ) + .arg( + Arg::with_name(options::OMIT_PROJECT_FILE) + .short("h") + .help("omit the user's project file in long format"), + ) + .arg( + Arg::with_name(options::OMIT_PLAN_FILE) + .short("p") + .help("omit the user's plan file in long format"), + ) + .arg( + Arg::with_name(options::SHORT_FORMAT) + .short("s") + .help("do short format output, this is the default"), + ) + .arg( + Arg::with_name(options::OMIT_HEADINGS) + .short("f") + .help("omit the line of column headings in short format"), + ) + .arg( + Arg::with_name(options::OMIT_NAME) + .short("w") + .help("omit the user's full name in short format"), + ) + .arg( + Arg::with_name(options::OMIT_NAME_HOST) + .short("i") + .help("omit the user's full name and remote host in short format"), + ) + .arg( + Arg::with_name(options::OMIT_NAME_HOST_TIME) + .short("q") + .help("omit the user's full name, remote host and idle time in short format"), + ) + .arg( + Arg::with_name(options::USER) + .takes_value(true) + .multiple(true), + ) + .get_matches_from(args); - let matches = opts.parse(args); + let users: Vec = matches + .values_of(options::USER) + .map(|v| v.map(ToString::to_string).collect()) + .unwrap_or_default(); // If true, display the hours:minutes since each user has touched // the keyboard, or blank if within the last minute, or days followed @@ -87,45 +130,40 @@ The utmp file will be {}", let mut include_idle = true; // If true, display a line at the top describing each field. - let include_heading = !matches.opt_present("f"); + let include_heading = !matches.is_present(options::OMIT_HEADINGS); // if true, display the user's full name from pw_gecos. let mut include_fullname = true; // if true, display the user's ~/.project file when doing long format. - let include_project = !matches.opt_present("h"); + let include_project = !matches.is_present(options::OMIT_PROJECT_FILE); // if true, display the user's ~/.plan file when doing long format. - let include_plan = !matches.opt_present("p"); + let include_plan = !matches.is_present(options::OMIT_PLAN_FILE); // if true, display the user's home directory and shell // when doing long format. - let include_home_and_shell = !matches.opt_present("b"); + let include_home_and_shell = !matches.is_present(options::OMIT_HOME_DIR); // if true, use the "short" output format. - let do_short_format = !matches.opt_present("l"); + let do_short_format = !matches.is_present(options::LONG_FORMAT); /* if true, display the ut_host field. */ let mut include_where = true; - if matches.opt_present("w") { + if matches.is_present(options::OMIT_NAME) { include_fullname = false; } - if matches.opt_present("i") { + if matches.is_present(options::OMIT_NAME_HOST) { include_fullname = false; include_where = false; } - if matches.opt_present("q") { + if matches.is_present(options::OMIT_NAME_HOST_TIME) { include_fullname = false; include_idle = false; include_where = false; } - if !do_short_format && matches.free.is_empty() { - show_usage_error!("no username specified; at least one must be specified when using -l"); - return 1; - } - let pk = Pinky { include_idle, include_heading, @@ -134,7 +172,7 @@ The utmp file will be {}", include_plan, include_home_and_shell, include_where, - names: matches.free, + names: users, }; if do_short_format { diff --git a/src/uu/printf/src/tokenize/num_format/formatters/base_conv/mod.rs b/src/uu/printf/src/tokenize/num_format/formatters/base_conv/mod.rs index 82971df3e..7d1d805c6 100644 --- a/src/uu/printf/src/tokenize/num_format/formatters/base_conv/mod.rs +++ b/src/uu/printf/src/tokenize/num_format/formatters/base_conv/mod.rs @@ -158,7 +158,6 @@ pub fn base_conv_float(src: &[u8], radix_src: u8, _radix_dest: u8) -> f64 { // to implement this for arbitrary string input. // until then, the below operates as an outline // of how it would work. - let result: Vec = vec![0]; let mut factor: f64 = 1_f64; let radix_src_float: f64 = f64::from(radix_src); let mut r: f64 = 0_f64; diff --git a/src/uu/sort/Cargo.toml b/src/uu/sort/Cargo.toml index 464207a2c..80ffc92c9 100644 --- a/src/uu/sort/Cargo.toml +++ b/src/uu/sort/Cargo.toml @@ -15,16 +15,19 @@ edition = "2018" path = "src/sort.rs" [dependencies] +serde_json = { version = "1.0.64", default-features = false, features = ["alloc"] } +serde = { version = "1.0", features = ["derive"] } rayon = "1.5" rand = "0.7" clap = "2.33" fnv = "1.0.7" itertools = "0.10.0" semver = "0.9.0" -smallvec = "1.6.1" +smallvec = { version="1.6.1", features=["serde"] } unicode-width = "0.1.8" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +tempdir = "0.3.7" [[bin]] name = "sort" diff --git a/src/uu/sort/src/custom_str_cmp.rs b/src/uu/sort/src/custom_str_cmp.rs new file mode 100644 index 000000000..a087a9fc2 --- /dev/null +++ b/src/uu/sort/src/custom_str_cmp.rs @@ -0,0 +1,64 @@ +// * This file is part of the uutils coreutils package. +// * +// * (c) Michael Debertol +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + +//! Custom string comparisons. +//! +//! The goal is to compare strings without transforming them first (i.e. not allocating new strings) + +use std::cmp::Ordering; + +fn filter_char(c: char, ignore_non_printing: bool, ignore_non_dictionary: bool) -> bool { + if ignore_non_dictionary && !(c.is_ascii_alphanumeric() || c.is_ascii_whitespace()) { + return false; + } + if ignore_non_printing && (c.is_ascii_control() || !c.is_ascii()) { + return false; + } + true +} + +fn cmp_chars(a: char, b: char, ignore_case: bool) -> Ordering { + if ignore_case { + a.to_ascii_uppercase().cmp(&b.to_ascii_uppercase()) + } else { + a.cmp(&b) + } +} + +pub fn custom_str_cmp( + a: &str, + b: &str, + ignore_non_printing: bool, + ignore_non_dictionary: bool, + ignore_case: bool, +) -> Ordering { + if !(ignore_case || ignore_non_dictionary || ignore_non_printing) { + // There are no custom settings. Fall back to the default strcmp, which is faster. + return a.cmp(&b); + } + let mut a_chars = a + .chars() + .filter(|&c| filter_char(c, ignore_non_printing, ignore_non_dictionary)); + let mut b_chars = b + .chars() + .filter(|&c| filter_char(c, ignore_non_printing, ignore_non_dictionary)); + loop { + let a_char = a_chars.next(); + let b_char = b_chars.next(); + match (a_char, b_char) { + (None, None) => return Ordering::Equal, + (Some(_), None) => return Ordering::Greater, + (None, Some(_)) => return Ordering::Less, + (Some(a_char), Some(b_char)) => { + let ordering = cmp_chars(a_char, b_char, ignore_case); + if ordering != Ordering::Equal { + return ordering; + } + } + } + } +} diff --git a/src/uu/sort/src/external_sort/LICENSE b/src/uu/sort/src/external_sort/LICENSE new file mode 100644 index 000000000..e26c89c9f --- /dev/null +++ b/src/uu/sort/src/external_sort/LICENSE @@ -0,0 +1,19 @@ +Copyright 2018 Battelle Memorial Institute + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/src/uu/sort/src/external_sort/mod.rs b/src/uu/sort/src/external_sort/mod.rs new file mode 100644 index 000000000..fd942d4a7 --- /dev/null +++ b/src/uu/sort/src/external_sort/mod.rs @@ -0,0 +1,295 @@ +use std::clone::Clone; +use std::cmp::Ordering::Less; +use std::collections::VecDeque; +use std::error::Error; +use std::fs::{File, OpenOptions}; +use std::io::SeekFrom::Start; +use std::io::{BufRead, BufReader, BufWriter, Seek, Write}; +use std::marker::PhantomData; +use std::path::PathBuf; + +use serde::de::DeserializeOwned; +use serde::Serialize; +use serde_json; +use tempdir::TempDir; + +use super::{GlobalSettings, Line}; + +/// Trait for types that can be used by +/// [ExternalSorter](struct.ExternalSorter.html). Must be sortable, cloneable, +/// serializeable, and able to report on it's size +pub trait ExternallySortable: Clone + Serialize + DeserializeOwned { + /// Get the size, in bytes, of this object (used to constrain the buffer + /// used in the external sort). + fn get_size(&self) -> u64; +} + +/// Iterator that provides sorted `T`s +pub struct ExtSortedIterator { + buffers: Vec>, + chunk_offsets: Vec, + max_per_chunk: u64, + chunks: u64, + tmp_dir: TempDir, + settings: GlobalSettings, + failed: bool, +} + +impl Iterator for ExtSortedIterator +where + Line: ExternallySortable, +{ + type Item = Result>; + + /// # Errors + /// + /// This method can fail due to issues reading intermediate sorted chunks + /// from disk, or due to serde deserialization issues + fn next(&mut self) -> Option { + if self.failed { + return None; + } + // fill up any empty buffers + let mut empty = true; + for chunk_num in 0..self.chunks { + if self.buffers[chunk_num as usize].is_empty() { + let mut f = match File::open(self.tmp_dir.path().join(chunk_num.to_string())) { + Ok(f) => f, + Err(e) => { + self.failed = true; + return Some(Err(Box::new(e))); + } + }; + match f.seek(Start(self.chunk_offsets[chunk_num as usize])) { + Ok(_) => (), + Err(e) => { + self.failed = true; + return Some(Err(Box::new(e))); + } + } + let bytes_read = + match fill_buff(&mut self.buffers[chunk_num as usize], f, self.max_per_chunk) { + Ok(bytes_read) => bytes_read, + Err(e) => { + self.failed = true; + return Some(Err(e)); + } + }; + self.chunk_offsets[chunk_num as usize] += bytes_read; + if !self.buffers[chunk_num as usize].is_empty() { + empty = false; + } + } else { + empty = false; + } + } + if empty { + return None; + } + + // find the next record to write + // check is_empty() before unwrap()ing + let mut idx = 0; + for chunk_num in 0..self.chunks as usize { + if !self.buffers[chunk_num].is_empty() { + if self.buffers[idx].is_empty() + || (super::compare_by)( + self.buffers[chunk_num].front().unwrap(), + self.buffers[idx].front().unwrap(), + &self.settings, + ) == Less + { + idx = chunk_num; + } + } + } + + // unwrap due to checks above + let r = self.buffers[idx].pop_front().unwrap(); + Some(Ok(r)) + } +} + +/// Perform an external sort on an unsorted stream of incoming data +pub struct ExternalSorter +where + Line: ExternallySortable, +{ + tmp_dir: Option, + buffer_bytes: u64, + phantom: PhantomData, + settings: GlobalSettings, +} + +impl ExternalSorter +where + Line: ExternallySortable, +{ + /// Create a new `ExternalSorter` with a specified memory buffer and + /// temporary directory + pub fn new( + buffer_bytes: u64, + tmp_dir: Option, + settings: GlobalSettings, + ) -> ExternalSorter { + ExternalSorter { + buffer_bytes, + tmp_dir, + phantom: PhantomData, + settings, + } + } + + /// Sort (based on `compare`) the `T`s provided by `unsorted` and return an + /// iterator + /// + /// # Errors + /// + /// This method can fail due to issues writing intermediate sorted chunks + /// to disk, or due to serde serialization issues + pub fn sort_by( + &self, + unsorted: I, + settings: GlobalSettings, + ) -> Result, Box> + where + I: Iterator, + { + let tmp_dir = match self.tmp_dir { + Some(ref p) => TempDir::new_in(p, "uutils_sort")?, + None => TempDir::new("uutils_sort")?, + }; + // creating the thing we need to return first due to the face that we need to + // borrow tmp_dir and move it out + let mut iter = ExtSortedIterator { + buffers: Vec::new(), + chunk_offsets: Vec::new(), + max_per_chunk: 0, + chunks: 0, + tmp_dir, + settings, + failed: false, + }; + + { + let mut total_read = 0; + let mut chunk = Vec::new(); + // Initial buffer is specified by user + let mut adjusted_buffer_size = self.buffer_bytes; + let (iter_size, _) = unsorted.size_hint(); + + // make the initial chunks on disk + for seq in unsorted { + let seq_size = seq.get_size(); + total_read += seq_size; + + // GNU minimum is 16 * (sizeof struct + 2), but GNU uses about + // 1/10 the memory that we do. And GNU even says in the code it may + // not work on small buffer sizes. + // + // The following seems to work pretty well, and has about the same max + // RSS as lower minimum values. + // + let minimum_buffer_size: u64 = iter_size as u64 * seq_size / 8; + + adjusted_buffer_size = + // Grow buffer size for a struct/Line larger than buffer + if adjusted_buffer_size < seq_size { + seq_size + } else if adjusted_buffer_size < minimum_buffer_size { + minimum_buffer_size + } else { + adjusted_buffer_size + }; + chunk.push(seq); + + if total_read >= adjusted_buffer_size { + super::sort_by(&mut chunk, &self.settings); + self.write_chunk( + &iter.tmp_dir.path().join(iter.chunks.to_string()), + &mut chunk, + )?; + chunk.clear(); + total_read = 0; + iter.chunks += 1; + } + } + // write the last chunk + if chunk.len() > 0 { + super::sort_by(&mut chunk, &self.settings); + self.write_chunk( + &iter.tmp_dir.path().join(iter.chunks.to_string()), + &mut chunk, + )?; + iter.chunks += 1; + } + + // initialize buffers for each chunk + // + // Having a right sized buffer for each chunk for smallish values seems silly to me? + // + // We will have to have the entire iter in memory sometime right? + // Set minimum to the size of the writer buffer, ~8K + // + const MINIMUM_READBACK_BUFFER: u64 = 8200; + let right_sized_buffer = adjusted_buffer_size + .checked_div(iter.chunks) + .unwrap_or(adjusted_buffer_size); + iter.max_per_chunk = if right_sized_buffer > MINIMUM_READBACK_BUFFER { + right_sized_buffer + } else { + MINIMUM_READBACK_BUFFER + }; + iter.buffers = vec![VecDeque::new(); iter.chunks as usize]; + iter.chunk_offsets = vec![0 as u64; iter.chunks as usize]; + for chunk_num in 0..iter.chunks { + let offset = fill_buff( + &mut iter.buffers[chunk_num as usize], + File::open(iter.tmp_dir.path().join(chunk_num.to_string()))?, + iter.max_per_chunk, + )?; + iter.chunk_offsets[chunk_num as usize] = offset; + } + } + + Ok(iter) + } + + fn write_chunk(&self, file: &PathBuf, chunk: &mut Vec) -> Result<(), Box> { + let new_file = OpenOptions::new().create(true).append(true).open(file)?; + let mut buf_write = Box::new(BufWriter::new(new_file)) as Box; + for s in chunk { + let mut serialized = serde_json::to_string(&s).expect("JSON write error: "); + serialized.push_str("\n"); + buf_write.write(serialized.as_bytes())?; + } + buf_write.flush()?; + + Ok(()) + } +} + +fn fill_buff( + vec: &mut VecDeque, + file: File, + max_bytes: u64, +) -> Result> +where + Line: ExternallySortable, +{ + let mut total_read = 0; + let mut bytes_read = 0; + for line in BufReader::new(file).lines() { + let line_s = line?; + bytes_read += line_s.len() + 1; + // This is where the bad stuff happens usually + let deserialized: Line = serde_json::from_str(&line_s).expect("JSON read error: "); + total_read += deserialized.get_size(); + vec.push_back(deserialized); + if total_read > max_bytes { + break; + } + } + + Ok(bytes_read as u64) +} diff --git a/src/uu/sort/src/numeric_str_cmp.rs b/src/uu/sort/src/numeric_str_cmp.rs index 314b4c595..b74d97867 100644 --- a/src/uu/sort/src/numeric_str_cmp.rs +++ b/src/uu/sort/src/numeric_str_cmp.rs @@ -14,20 +14,21 @@ //! More specifically, exponent can be understood so that the original number is in (1..10)*10^exponent. //! From that follows the constraints of this algorithm: It is able to compare numbers in ±(1*10^[i64::MIN]..10*10^[i64::MAX]). +use serde::{Deserialize, Serialize}; use std::{cmp::Ordering, ops::Range}; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)] enum Sign { Negative, Positive, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] pub struct NumInfo { exponent: i64, sign: Sign, } - +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] pub struct NumInfoParseSettings { pub accept_si_units: bool, pub thousands_separator: Option, diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index de19d0a5c..c82524796 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -15,9 +15,13 @@ #[macro_use] extern crate uucore; +mod custom_str_cmp; +mod external_sort; mod numeric_str_cmp; use clap::{App, Arg}; +use custom_str_cmp::custom_str_cmp; +use external_sort::{ExternalSorter, ExternallySortable}; use fnv::FnvHasher; use itertools::Itertools; use numeric_str_cmp::{numeric_str_cmp, NumInfo, NumInfoParseSettings}; @@ -25,6 +29,7 @@ use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use rayon::prelude::*; use semver::Version; +use serde::{Deserialize, Serialize}; use smallvec::SmallVec; use std::cmp::Ordering; use std::collections::BinaryHeap; @@ -35,6 +40,7 @@ use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Lines, Read, Write}; use std::mem::replace; use std::ops::Range; use std::path::Path; +use std::path::PathBuf; use unicode_width::UnicodeWidthStr; use uucore::fs::is_stdin_interactive; // for Iterator::dedup() use uucore::InvalidEncodingHandling; @@ -77,6 +83,8 @@ static OPT_RANDOM: &str = "random-sort"; static OPT_ZERO_TERMINATED: &str = "zero-terminated"; static OPT_PARALLEL: &str = "parallel"; static OPT_FILES0_FROM: &str = "files0-from"; +static OPT_BUF_SIZE: &str = "buffer-size"; +static OPT_TMP_DIR: &str = "temporary-directory"; static ARG_FILES: &str = "files"; @@ -86,6 +94,8 @@ static THOUSANDS_SEP: char = ','; static NEGATIVE: char = '-'; static POSITIVE: char = '+'; +static DEFAULT_BUF_SIZE: usize = std::usize::MAX; + #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Copy)] enum SortMode { Numeric, @@ -95,7 +105,7 @@ enum SortMode { Version, Default, } - +#[derive(Clone)] struct GlobalSettings { mode: SortMode, debug: bool, @@ -116,6 +126,31 @@ struct GlobalSettings { separator: Option, threads: String, zero_terminated: bool, + buffer_size: usize, + tmp_dir: PathBuf, + ext_sort: bool, +} + +impl GlobalSettings { + // It's back to do conversions for command line opts! + // Probably want to do through numstrcmp somehow now? + fn human_numeric_convert(a: &str) -> usize { + let num_str = &a[get_leading_gen(a)]; + let (_, suf_str) = a.split_at(num_str.len()); + let num_usize = num_str + .parse::() + .expect("Error parsing buffer size: "); + let suf_usize: usize = match suf_str.to_uppercase().as_str() { + // SI Units + "B" => 1usize, + "K" => 1000usize, + "M" => 1000000usize, + "G" => 1000000000usize, + // GNU regards empty human numeric values as K by default + _ => 1000usize, + }; + num_usize * suf_usize + } } impl Default for GlobalSettings { @@ -140,10 +175,13 @@ impl Default for GlobalSettings { separator: None, threads: String::new(), zero_terminated: false, + buffer_size: DEFAULT_BUF_SIZE, + tmp_dir: PathBuf::new(), + ext_sort: false, } } } - +#[derive(Clone)] struct KeySettings { mode: SortMode, ignore_blanks: bool, @@ -168,37 +206,29 @@ impl From<&GlobalSettings> for KeySettings { } } +#[derive(Debug, Serialize, Deserialize, Clone)] /// Represents the string selected by a FieldSelector. -enum SelectionRange { - /// If we had to transform this selection, we have to store a new string. - String(String), - /// If there was no transformation, we can store an index into the line. - ByIndex(Range), +struct SelectionRange { + range: Range, } impl SelectionRange { + fn new(range: Range) -> Self { + Self { range } + } + /// Gets the actual string slice represented by this Selection. - fn get_str<'a>(&'a self, line: &'a str) -> &'a str { - match self { - SelectionRange::String(string) => string.as_str(), - SelectionRange::ByIndex(range) => &line[range.to_owned()], - } + fn get_str<'a>(&self, line: &'a str) -> &'a str { + &line[self.range.to_owned()] } fn shorten(&mut self, new_range: Range) { - match self { - SelectionRange::String(string) => { - string.drain(new_range.end..); - string.drain(..new_range.start); - } - SelectionRange::ByIndex(range) => { - range.end = range.start + new_range.end; - range.start += new_range.start; - } - } + self.range.end = self.range.start + new_range.end; + self.range.start += new_range.start; } } +#[derive(Serialize, Deserialize, Clone)] enum NumCache { AsF64(GeneralF64ParseResult), WithInfo(NumInfo), @@ -219,7 +249,7 @@ impl NumCache { } } } - +#[derive(Serialize, Deserialize, Clone)] struct Selection { range: SelectionRange, num_cache: NumCache, @@ -234,12 +264,20 @@ impl Selection { type Field = Range; +#[derive(Serialize, Deserialize, Clone)] struct Line { line: String, // The common case is not to specify fields. Let's make this fast. selections: SmallVec<[Selection; 1]>, } +impl ExternallySortable for Line { + fn get_size(&self) -> u64 { + // Currently 96 bytes, but that could change, so we get that size here + std::mem::size_of::() as u64 + } +} + impl Line { fn new(line: String, settings: &GlobalSettings) -> Self { let fields = if settings @@ -257,14 +295,8 @@ impl Line { .selectors .iter() .map(|selector| { - let range = selector.get_selection(&line, fields.as_deref()); - let mut range = if let Some(transformed) = - transform(&line[range.to_owned()], &selector.settings) - { - SelectionRange::String(transformed) - } else { - SelectionRange::ByIndex(range) - }; + let mut range = + SelectionRange::new(selector.get_selection(&line, fields.as_deref())); let num_cache = if selector.settings.mode == SortMode::Numeric || selector.settings.mode == SortMode::HumanNumeric { @@ -414,34 +446,6 @@ impl Line { } } -/// Transform this line. Returns None if there's no need to transform. -fn transform(line: &str, settings: &KeySettings) -> Option { - let mut transformed = None; - if settings.ignore_case { - transformed = Some(line.to_uppercase()); - } - if settings.ignore_blanks { - transformed = Some( - transformed - .as_deref() - .unwrap_or(line) - .trim_start() - .to_string(), - ); - } - if settings.dictionary_order { - transformed = Some(remove_nondictionary_chars( - transformed.as_deref().unwrap_or(line), - )); - } - if settings.ignore_non_printing { - transformed = Some(remove_nonprinting_chars( - transformed.as_deref().unwrap_or(line), - )); - } - transformed -} - /// Tokenize a line into fields. fn tokenize(line: &str, separator: Option) -> Vec { if let Some(separator) = separator { @@ -489,6 +493,7 @@ fn tokenize_with_separator(line: &str, separator: char) -> Vec { tokens } +#[derive(Clone)] struct KeyPosition { /// 1-indexed, 0 is invalid. field: usize, @@ -578,7 +583,7 @@ impl KeyPosition { } } } - +#[derive(Clone)] struct FieldSelector { from: KeyPosition, to: Option, @@ -912,6 +917,22 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .takes_value(true) .value_name("NUM_THREADS"), ) + .arg( + Arg::with_name(OPT_BUF_SIZE) + .short("S") + .long(OPT_BUF_SIZE) + .help("sets the maximum SIZE of each segment in number of sorted items") + .takes_value(true) + .value_name("SIZE"), + ) + .arg( + Arg::with_name(OPT_TMP_DIR) + .short("T") + .long(OPT_TMP_DIR) + .help("use DIR for temporaries, not $TMPDIR or /tmp") + .takes_value(true) + .value_name("DIR"), + ) .arg( Arg::with_name(OPT_FILES0_FROM) .long(OPT_FILES0_FROM) @@ -982,6 +1003,29 @@ pub fn uumain(args: impl uucore::Args) -> i32 { env::set_var("RAYON_NUM_THREADS", &settings.threads); } + if matches.is_present(OPT_BUF_SIZE) { + settings.buffer_size = { + let input = matches + .value_of(OPT_BUF_SIZE) + .map(String::from) + .unwrap_or(format!("{}", DEFAULT_BUF_SIZE)); + + GlobalSettings::human_numeric_convert(&input) + }; + settings.ext_sort = true; + } + + if matches.is_present(OPT_TMP_DIR) { + let result = matches + .value_of(OPT_TMP_DIR) + .map(String::from) + .unwrap_or(format!("{}", env::temp_dir().display())); + settings.tmp_dir = PathBuf::from(result); + settings.ext_sort = true; + } else { + settings.tmp_dir = env::temp_dir(); + } + settings.zero_terminated = matches.is_present(OPT_ZERO_TERMINATED); settings.merge = matches.is_present(OPT_MERGE); @@ -1066,10 +1110,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { }); } - exec(files, &settings) + exec(files, settings) } -fn exec(files: Vec, settings: &GlobalSettings) -> i32 { +fn exec(files: Vec, settings: GlobalSettings) -> i32 { let mut lines = Vec::new(); let mut file_merger = FileMerger::new(&settings); @@ -1105,6 +1149,13 @@ fn exec(files: Vec, settings: &GlobalSettings) -> i32 { if settings.check { return exec_check_file(&lines, &settings); + } + + // Only use ext_sorter when we need to. + // Probably faster that we don't create + // an owned value each run + if settings.ext_sort { + lines = ext_sort_by(lines, settings.clone()); } else { sort_by(&mut lines, &settings); } @@ -1112,7 +1163,7 @@ fn exec(files: Vec, settings: &GlobalSettings) -> i32 { if settings.merge { if settings.unique { print_sorted( - file_merger.dedup_by(|a, b| compare_by(a, b, settings) == Ordering::Equal), + file_merger.dedup_by(|a, b| compare_by(a, b, &settings) == Ordering::Equal), &settings, ) } else { @@ -1122,7 +1173,7 @@ fn exec(files: Vec, settings: &GlobalSettings) -> i32 { print_sorted( lines .into_iter() - .dedup_by(|a, b| compare_by(a, b, settings) == Ordering::Equal), + .dedup_by(|a, b| compare_by(a, b, &settings) == Ordering::Equal), &settings, ) } else { @@ -1164,11 +1215,25 @@ fn exec_check_file(unwrapped_lines: &[Line], settings: &GlobalSettings) -> i32 { } } -fn sort_by(lines: &mut Vec, settings: &GlobalSettings) { +fn ext_sort_by(unsorted: Vec, settings: GlobalSettings) -> Vec { + let external_sorter = ExternalSorter::new( + settings.buffer_size as u64, + Some(settings.tmp_dir.clone()), + settings.clone(), + ); + let iter = external_sorter + .sort_by(unsorted.into_iter(), settings) + .unwrap() + .map(|x| x.unwrap()) + .collect::>(); + iter +} + +fn sort_by(unsorted: &mut Vec, settings: &GlobalSettings) { if settings.stable || settings.unique { - lines.par_sort_by(|a, b| compare_by(a, b, &settings)) + unsorted.par_sort_by(|a, b| compare_by(a, b, &settings)) } else { - lines.par_sort_unstable_by(|a, b| compare_by(a, b, &settings)) + unsorted.par_sort_unstable_by(|a, b| compare_by(a, b, &settings)) } } @@ -1194,7 +1259,13 @@ fn compare_by(a: &Line, b: &Line, global_settings: &GlobalSettings) -> Ordering ), SortMode::Month => month_compare(a_str, b_str), SortMode::Version => version_compare(a_str, b_str), - SortMode::Default => default_compare(a_str, b_str), + SortMode::Default => custom_str_cmp( + a_str, + b_str, + settings.ignore_non_printing, + settings.dictionary_order, + settings.ignore_case, + ), } }; if cmp != Ordering::Equal { @@ -1206,7 +1277,7 @@ fn compare_by(a: &Line, b: &Line, global_settings: &GlobalSettings) -> Ordering let cmp = if global_settings.random || global_settings.stable || global_settings.unique { Ordering::Equal } else { - default_compare(&a.line, &b.line) + a.line.cmp(&b.line) }; if global_settings.reverse { @@ -1216,13 +1287,6 @@ fn compare_by(a: &Line, b: &Line, global_settings: &GlobalSettings) -> Ordering } } -// Test output against BSDs and GNU with their locale -// env var set to lc_ctype=utf-8 to enjoy the exact same output. -#[inline(always)] -fn default_compare(a: &str, b: &str) -> Ordering { - a.cmp(b) -} - // This function cleans up the initial comparison done by leading_num_common for a general numeric compare. // In contrast to numeric compare, GNU general numeric/FP sort *should* recognize positive signs and // scientific notation, so we strip those lines only after the end of the following numeric string. @@ -1268,7 +1332,7 @@ fn get_leading_gen(input: &str) -> Range { leading_whitespace_len..input.len() } -#[derive(Copy, Clone, PartialEq, PartialOrd)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, PartialOrd)] enum GeneralF64ParseResult { Invalid, NaN, @@ -1409,22 +1473,6 @@ fn version_compare(a: &str, b: &str) -> Ordering { } } -fn remove_nondictionary_chars(s: &str) -> String { - // According to GNU, dictionary chars are those of ASCII - // and a blank is a space or a tab - s.chars() - .filter(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace()) - .collect::() -} - -fn remove_nonprinting_chars(s: &str) -> String { - // However, GNU says nonprinting chars are more permissive. - // All of ASCII except control chars ie, escape, newline - s.chars() - .filter(|c| c.is_ascii() && !c.is_ascii_control()) - .collect::() -} - fn print_sorted>(iter: T, settings: &GlobalSettings) { let mut file: Box = match settings.outfile { Some(ref filename) => match File::create(Path::new(&filename)) { @@ -1491,14 +1539,6 @@ mod tests { assert_eq!(Ordering::Equal, random_shuffle(a, b, c)); } - #[test] - fn test_default_compare() { - let a = "your own"; - let b = "your place"; - - assert_eq!(Ordering::Less, default_compare(a, b)); - } - #[test] fn test_month_compare() { let a = "JaN"; diff --git a/src/uu/test/src/parser.rs b/src/uu/test/src/parser.rs new file mode 100644 index 000000000..f1ca9dad6 --- /dev/null +++ b/src/uu/test/src/parser.rs @@ -0,0 +1,292 @@ +// This file is part of the uutils coreutils package. +// +// (c) Daniel Rocco +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +use std::ffi::OsString; +use std::iter::Peekable; + +/// Represents a parsed token from a test expression +#[derive(Debug, PartialEq)] +pub enum Symbol { + LParen, + Bang, + BoolOp(OsString), + Literal(OsString), + StringOp(OsString), + IntOp(OsString), + FileOp(OsString), + StrlenOp(OsString), + FiletestOp(OsString), + None, +} + +impl Symbol { + /// Create a new Symbol from an OsString. + /// + /// Returns Symbol::None in place of None + fn new(token: Option) -> Symbol { + match token { + Some(s) => match s.to_string_lossy().as_ref() { + "(" => Symbol::LParen, + "!" => Symbol::Bang, + "-a" | "-o" => Symbol::BoolOp(s), + "=" | "!=" => Symbol::StringOp(s), + "-eq" | "-ge" | "-gt" | "-le" | "-lt" | "-ne" => Symbol::IntOp(s), + "-ef" | "-nt" | "-ot" => Symbol::FileOp(s), + "-n" | "-z" => Symbol::StrlenOp(s), + "-b" | "-c" | "-d" | "-e" | "-f" | "-g" | "-G" | "-h" | "-k" | "-L" | "-O" + | "-p" | "-r" | "-s" | "-S" | "-t" | "-u" | "-w" | "-x" => Symbol::FiletestOp(s), + _ => Symbol::Literal(s), + }, + None => Symbol::None, + } + } + + /// Convert this Symbol into a Symbol::Literal, useful for cases where + /// test treats an operator as a string operand (test has no reserved + /// words). + /// + /// # Panics + /// + /// Panics if `self` is Symbol::None + fn into_literal(self) -> Symbol { + Symbol::Literal(match self { + Symbol::LParen => OsString::from("("), + Symbol::Bang => OsString::from("!"), + Symbol::BoolOp(s) + | Symbol::Literal(s) + | Symbol::StringOp(s) + | Symbol::IntOp(s) + | Symbol::FileOp(s) + | Symbol::StrlenOp(s) + | Symbol::FiletestOp(s) => s, + Symbol::None => panic!(), + }) + } +} + +/// Recursive descent parser for test, which converts a list of OsStrings +/// (typically command line arguments) into a stack of Symbols in postfix +/// order. +/// +/// Grammar: +/// +/// EXPR → TERM | EXPR BOOLOP EXPR +/// TERM → ( EXPR ) +/// TERM → ( ) +/// TERM → ! EXPR +/// TERM → UOP str +/// UOP → STRLEN | FILETEST +/// TERM → str OP str +/// TERM → str | 𝜖 +/// OP → STRINGOP | INTOP | FILEOP +/// STRINGOP → = | != +/// INTOP → -eq | -ge | -gt | -le | -lt | -ne +/// FILEOP → -ef | -nt | -ot +/// STRLEN → -n | -z +/// FILETEST → -b | -c | -d | -e | -f | -g | -G | -h | -k | -L | -O | -p | +/// -r | -s | -S | -t | -u | -w | -x +/// BOOLOP → -a | -o +/// +#[derive(Debug)] +struct Parser { + tokens: Peekable>, + pub stack: Vec, +} + +impl Parser { + /// Construct a new Parser from a `Vec` of tokens. + fn new(tokens: Vec) -> Parser { + Parser { + tokens: tokens.into_iter().peekable(), + stack: vec![], + } + } + + /// Fetch the next token from the input stream as a Symbol. + fn next_token(&mut self) -> Symbol { + Symbol::new(self.tokens.next()) + } + + /// Peek at the next token from the input stream, returning it as a Symbol. + /// The stream is unchanged and will return the same Symbol on subsequent + /// calls to `next()` or `peek()`. + fn peek(&mut self) -> Symbol { + Symbol::new(self.tokens.peek().map(|s| s.to_os_string())) + } + + /// Test if the next token in the stream is a BOOLOP (-a or -o), without + /// removing the token from the stream. + fn peek_is_boolop(&mut self) -> bool { + if let Symbol::BoolOp(_) = self.peek() { + true + } else { + false + } + } + + /// Parse an expression. + /// + /// EXPR → TERM | EXPR BOOLOP EXPR + fn expr(&mut self) { + if !self.peek_is_boolop() { + self.term(); + } + self.maybe_boolop(); + } + + /// Parse a term token and possible subsequent symbols: "(", "!", UOP, + /// literal, or None. + fn term(&mut self) { + let symbol = self.next_token(); + + match symbol { + Symbol::LParen => self.lparen(), + Symbol::Bang => self.bang(), + Symbol::StrlenOp(_) => self.uop(symbol), + Symbol::FiletestOp(_) => self.uop(symbol), + Symbol::None => self.stack.push(symbol), + literal => self.literal(literal), + } + } + + /// Parse a (possibly) parenthesized expression. + /// + /// test has no reserved keywords, so "(" will be interpreted as a literal + /// if it is followed by nothing or a comparison operator OP. + fn lparen(&mut self) { + match self.peek() { + // lparen is a literal when followed by nothing or comparison + Symbol::None | Symbol::StringOp(_) | Symbol::IntOp(_) | Symbol::FileOp(_) => { + self.literal(Symbol::Literal(OsString::from("("))); + } + // empty parenthetical + Symbol::Literal(s) if s == ")" => {} + _ => { + self.expr(); + match self.next_token() { + Symbol::Literal(s) if s == ")" => (), + _ => panic!("expected ‘)’"), + } + } + } + } + + /// Parse a (possibly) negated expression. + /// + /// Example cases: + /// + /// * `! =`: negate the result of the implicit string length test of `=` + /// * `! = foo`: compare the literal strings `!` and `foo` + /// * `! `: negate the result of the expression + /// + fn bang(&mut self) { + if let Symbol::StringOp(_) | Symbol::IntOp(_) | Symbol::FileOp(_) = self.peek() { + // we need to peek ahead one more token to disambiguate the first + // two cases listed above: case 1 — `! ` — and + // case 2: ` OP str`. + let peek2 = self.tokens.clone().nth(1); + + if peek2.is_none() { + // op is literal + let op = self.next_token().into_literal(); + self.stack.push(op); + self.stack.push(Symbol::Bang); + } else { + // bang is literal; parsing continues with op + self.literal(Symbol::Literal(OsString::from("!"))); + } + } else { + self.expr(); + self.stack.push(Symbol::Bang); + } + } + + /// Peek at the next token and parse it as a BOOLOP or string literal, + /// as appropriate. + fn maybe_boolop(&mut self) { + if self.peek_is_boolop() { + let token = self.tokens.next().unwrap(); // safe because we peeked + + // BoolOp by itself interpreted as Literal + if let Symbol::None = self.peek() { + self.literal(Symbol::Literal(token)) + } else { + self.boolop(Symbol::BoolOp(token)) + } + } + } + + /// Parse a Boolean expression. + /// + /// Logical and (-a) has higher precedence than or (-o), so in an + /// expression like `foo -o '' -a ''`, the and subexpression is evaluated + /// first. + fn boolop(&mut self, op: Symbol) { + if op == Symbol::BoolOp(OsString::from("-a")) { + self.term(); + self.stack.push(op); + self.maybe_boolop(); + } else { + self.expr(); + self.stack.push(op); + } + } + + /// Parse a (possible) unary argument test (string length or file + /// attribute check). + /// + /// If a UOP is followed by nothing it is interpreted as a literal string. + fn uop(&mut self, op: Symbol) { + match self.next_token() { + Symbol::None => self.stack.push(op.into_literal()), + symbol => { + self.stack.push(symbol.into_literal()); + self.stack.push(op); + } + } + } + + /// Parse a string literal, optionally followed by a comparison operator + /// and a second string literal. + fn literal(&mut self, token: Symbol) { + self.stack.push(token.into_literal()); + + // EXPR → str OP str + match self.peek() { + Symbol::StringOp(_) | Symbol::IntOp(_) | Symbol::FileOp(_) => { + let op = self.next_token(); + + match self.next_token() { + Symbol::None => panic!("missing argument after {:?}", op), + token => self.stack.push(token.into_literal()), + } + + self.stack.push(op); + } + _ => {} + } + } + + /// Parser entry point: parse the token stream `self.tokens`, storing the + /// resulting `Symbol` stack in `self.stack`. + fn parse(&mut self) -> Result<(), String> { + self.expr(); + + match self.tokens.next() { + Some(token) => Err(format!("extra argument ‘{}’", token.to_string_lossy())), + None => Ok(()), + } + } +} + +/// Parse the token stream `args`, returning a `Symbol` stack representing the +/// operations to perform in postfix order. +pub fn parse(args: Vec) -> Result, String> { + let mut p = Parser::new(args); + p.parse()?; + Ok(p.stack) +} diff --git a/src/uu/test/src/test.rs b/src/uu/test/src/test.rs index f882ff5ae..3e97af0a6 100644 --- a/src/uu/test/src/test.rs +++ b/src/uu/test/src/test.rs @@ -1,144 +1,154 @@ -// * This file is part of the uutils coreutils package. -// * -// * (c) mahkoh (ju.orth [at] gmail [dot] com) -// * -// * For the full copyright and license information, please view the LICENSE -// * file that was distributed with this source code. +// This file is part of the uutils coreutils package. +// +// (c) mahkoh (ju.orth [at] gmail [dot] com) +// (c) Daniel Rocco +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. // spell-checker:ignore (ToDO) retval paren prec subprec cond -use std::collections::HashMap; -use std::str::from_utf8; +mod parser; -static NAME: &str = "test"; +use parser::{parse, Symbol}; +use std::ffi::{OsStr, OsString}; pub fn uumain(args: impl uucore::Args) -> i32 { - let args: Vec<_> = args.collect(); - // This is completely disregarding valid windows paths that aren't valid unicode - let args = args - .iter() - .map(|a| a.to_str().unwrap().as_bytes()) - .collect::>(); - if args.is_empty() { - return 2; - } - let args = if !args[0].ends_with(NAME.as_bytes()) { - &args[1..] - } else { - &args[..] - }; - let args = match args[0] { - b"[" => match args[args.len() - 1] { - b"]" => &args[1..args.len() - 1], - _ => return 2, - }, - _ => &args[1..args.len()], - }; - let mut error = false; - let retval = 1 - parse_expr(args, &mut error) as i32; - if error { - 2 - } else { - retval - } -} + // TODO: handle being called as `[` + let args: Vec<_> = args.skip(1).collect(); -fn one(args: &[&[u8]]) -> bool { - !args[0].is_empty() -} + let result = parse(args).and_then(|mut stack| eval(&mut stack)); -fn two(args: &[&[u8]], error: &mut bool) -> bool { - match args[0] { - b"!" => !one(&args[1..]), - b"-b" => path(args[1], PathCondition::BlockSpecial), - b"-c" => path(args[1], PathCondition::CharacterSpecial), - b"-d" => path(args[1], PathCondition::Directory), - b"-e" => path(args[1], PathCondition::Exists), - b"-f" => path(args[1], PathCondition::Regular), - b"-g" => path(args[1], PathCondition::GroupIdFlag), - b"-h" => path(args[1], PathCondition::SymLink), - b"-L" => path(args[1], PathCondition::SymLink), - b"-n" => one(&args[1..]), - b"-p" => path(args[1], PathCondition::Fifo), - b"-r" => path(args[1], PathCondition::Readable), - b"-S" => path(args[1], PathCondition::Socket), - b"-s" => path(args[1], PathCondition::NonEmpty), - b"-t" => isatty(args[1]), - b"-u" => path(args[1], PathCondition::UserIdFlag), - b"-w" => path(args[1], PathCondition::Writable), - b"-x" => path(args[1], PathCondition::Executable), - b"-z" => !one(&args[1..]), - _ => { - *error = true; - false - } - } -} - -fn three(args: &[&[u8]], error: &mut bool) -> bool { - match args[1] { - b"=" => args[0] == args[2], - b"==" => args[0] == args[2], - b"!=" => args[0] != args[2], - b"-eq" => integers(args[0], args[2], IntegerCondition::Equal), - b"-ne" => integers(args[0], args[2], IntegerCondition::Unequal), - b"-gt" => integers(args[0], args[2], IntegerCondition::Greater), - b"-ge" => integers(args[0], args[2], IntegerCondition::GreaterEqual), - b"-lt" => integers(args[0], args[2], IntegerCondition::Less), - b"-le" => integers(args[0], args[2], IntegerCondition::LessEqual), - _ => match args[0] { - b"!" => !two(&args[1..], error), - _ => { - *error = true; - false + match result { + Ok(result) => { + if result { + 0 + } else { + 1 } - }, - } -} - -fn four(args: &[&[u8]], error: &mut bool) -> bool { - match args[0] { - b"!" => !three(&args[1..], error), - _ => { - *error = true; - false + } + Err(e) => { + eprintln!("test: {}", e); + 2 } } } -enum IntegerCondition { - Equal, - Unequal, - Greater, - GreaterEqual, - Less, - LessEqual, -} +/// Evaluate a stack of Symbols, returning the result of the evaluation or +/// an error message if evaluation failed. +fn eval(stack: &mut Vec) -> Result { + macro_rules! pop_literal { + () => { + match stack.pop() { + Some(Symbol::Literal(s)) => s, + _ => panic!(), + } + }; + } -fn integers(a: &[u8], b: &[u8], cond: IntegerCondition) -> bool { - let (a, b): (&str, &str) = match (from_utf8(a), from_utf8(b)) { - (Ok(a), Ok(b)) => (a, b), - _ => return false, - }; - let (a, b): (i64, i64) = match (a.parse(), b.parse()) { - (Ok(a), Ok(b)) => (a, b), - _ => return false, - }; - match cond { - IntegerCondition::Equal => a == b, - IntegerCondition::Unequal => a != b, - IntegerCondition::Greater => a > b, - IntegerCondition::GreaterEqual => a >= b, - IntegerCondition::Less => a < b, - IntegerCondition::LessEqual => a <= b, + let s = stack.pop(); + + match s { + Some(Symbol::Bang) => { + let result = eval(stack)?; + + Ok(!result) + } + Some(Symbol::StringOp(op)) => { + let b = stack.pop(); + let a = stack.pop(); + Ok(if op == "=" { a == b } else { a != b }) + } + Some(Symbol::IntOp(op)) => { + let b = pop_literal!(); + let a = pop_literal!(); + + Ok(integers(&a, &b, &op)?) + } + Some(Symbol::FileOp(_op)) => unimplemented!(), + Some(Symbol::StrlenOp(op)) => { + let s = match stack.pop() { + Some(Symbol::Literal(s)) => s, + Some(Symbol::None) => OsString::from(""), + None => { + return Ok(true); + } + _ => { + return Err(format!("missing argument after ‘{:?}’", op)); + } + }; + + Ok(if op == "-z" { + s.is_empty() + } else { + !s.is_empty() + }) + } + Some(Symbol::FiletestOp(op)) => { + let op = op.to_string_lossy(); + + let f = pop_literal!(); + + Ok(match op.as_ref() { + "-b" => path(&f, PathCondition::BlockSpecial), + "-c" => path(&f, PathCondition::CharacterSpecial), + "-d" => path(&f, PathCondition::Directory), + "-e" => path(&f, PathCondition::Exists), + "-f" => path(&f, PathCondition::Regular), + "-g" => path(&f, PathCondition::GroupIdFlag), + "-h" => path(&f, PathCondition::SymLink), + "-L" => path(&f, PathCondition::SymLink), + "-p" => path(&f, PathCondition::Fifo), + "-r" => path(&f, PathCondition::Readable), + "-S" => path(&f, PathCondition::Socket), + "-s" => path(&f, PathCondition::NonEmpty), + "-t" => isatty(&f)?, + "-u" => path(&f, PathCondition::UserIdFlag), + "-w" => path(&f, PathCondition::Writable), + "-x" => path(&f, PathCondition::Executable), + _ => panic!(), + }) + } + Some(Symbol::Literal(s)) => Ok(!s.is_empty()), + Some(Symbol::None) => Ok(false), + Some(Symbol::BoolOp(op)) => { + let b = eval(stack)?; + let a = eval(stack)?; + + Ok(if op == "-a" { a && b } else { a || b }) + } + None => Ok(false), + _ => Err("expected value".to_string()), } } -fn isatty(fd: &[u8]) -> bool { - from_utf8(fd) - .ok() - .and_then(|s| s.parse().ok()) - .map_or(false, |i| { +fn integers(a: &OsStr, b: &OsStr, cond: &OsStr) -> Result { + let format_err = |value| format!("invalid integer ‘{}’", value); + + let a = a.to_string_lossy(); + let a: i64 = a.parse().map_err(|_| format_err(a))?; + + let b = b.to_string_lossy(); + let b: i64 = b.parse().map_err(|_| format_err(b))?; + + let cond = cond.to_string_lossy(); + Ok(match cond.as_ref() { + "-eq" => a == b, + "-ne" => a != b, + "-gt" => a > b, + "-ge" => a >= b, + "-lt" => a < b, + "-le" => a <= b, + _ => return Err(format!("unknown operator ‘{}’", cond)), + }) +} + +fn isatty(fd: &OsStr) -> Result { + let fd = fd.to_string_lossy(); + + fd.parse() + .map_err(|_| format!("invalid integer ‘{}’", fd)) + .map(|i| { #[cfg(not(target_os = "redox"))] unsafe { libc::isatty(i) == 1 @@ -148,173 +158,6 @@ fn isatty(fd: &[u8]) -> bool { }) } -fn dispatch(args: &mut &[&[u8]], error: &mut bool) -> bool { - let (val, idx) = match args.len() { - 0 => { - *error = true; - (false, 0) - } - 1 => (one(*args), 1), - 2 => dispatch_two(args, error), - 3 => dispatch_three(args, error), - _ => dispatch_four(args, error), - }; - *args = &(*args)[idx..]; - val -} - -fn dispatch_two(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { - let val = two(*args, error); - if *error { - *error = false; - (one(*args), 1) - } else { - (val, 2) - } -} - -fn dispatch_three(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { - let val = three(*args, error); - if *error { - *error = false; - dispatch_two(args, error) - } else { - (val, 3) - } -} - -fn dispatch_four(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { - let val = four(*args, error); - if *error { - *error = false; - dispatch_three(args, error) - } else { - (val, 4) - } -} - -#[derive(Clone, Copy)] -enum Precedence { - Unknown = 0, - Paren, // FIXME: this is useless (parentheses have not been implemented) - Or, - And, - BUnOp, - BinOp, - UnOp, -} - -fn parse_expr(mut args: &[&[u8]], error: &mut bool) -> bool { - if args.is_empty() { - false - } else { - let hashmap = setup_hashmap(); - let lhs = dispatch(&mut args, error); - - if !args.is_empty() { - parse_expr_helper(&hashmap, &mut args, lhs, Precedence::Unknown, error) - } else { - lhs - } - } -} - -fn parse_expr_helper<'a>( - hashmap: &HashMap<&'a [u8], Precedence>, - args: &mut &[&'a [u8]], - mut lhs: bool, - min_prec: Precedence, - error: &mut bool, -) -> bool { - let mut prec = *hashmap.get(&args[0]).unwrap_or_else(|| { - *error = true; - &min_prec - }); - while !*error && !args.is_empty() && prec as usize >= min_prec as usize { - let op = args[0]; - *args = &(*args)[1..]; - let mut rhs = dispatch(args, error); - while !args.is_empty() { - let subprec = *hashmap.get(&args[0]).unwrap_or_else(|| { - *error = true; - &min_prec - }); - if subprec as usize <= prec as usize || *error { - break; - } - rhs = parse_expr_helper(hashmap, args, rhs, subprec, error); - } - lhs = match prec { - Precedence::UnOp | Precedence::BUnOp => { - *error = true; - false - } - Precedence::And => lhs && rhs, - Precedence::Or => lhs || rhs, - Precedence::BinOp => three( - &[ - if lhs { b" " } else { b"" }, - op, - if rhs { b" " } else { b"" }, - ], - error, - ), - Precedence::Paren => unimplemented!(), // TODO: implement parentheses - _ => unreachable!(), - }; - if !args.is_empty() { - prec = *hashmap.get(&args[0]).unwrap_or_else(|| { - *error = true; - &min_prec - }); - } - } - lhs -} - -#[inline] -fn setup_hashmap<'a>() -> HashMap<&'a [u8], Precedence> { - let mut hashmap = HashMap::<&'a [u8], Precedence>::new(); - - hashmap.insert(b"-b", Precedence::UnOp); - hashmap.insert(b"-c", Precedence::UnOp); - hashmap.insert(b"-d", Precedence::UnOp); - hashmap.insert(b"-e", Precedence::UnOp); - hashmap.insert(b"-f", Precedence::UnOp); - hashmap.insert(b"-g", Precedence::UnOp); - hashmap.insert(b"-h", Precedence::UnOp); - hashmap.insert(b"-L", Precedence::UnOp); - hashmap.insert(b"-n", Precedence::UnOp); - hashmap.insert(b"-p", Precedence::UnOp); - hashmap.insert(b"-r", Precedence::UnOp); - hashmap.insert(b"-S", Precedence::UnOp); - hashmap.insert(b"-s", Precedence::UnOp); - hashmap.insert(b"-t", Precedence::UnOp); - hashmap.insert(b"-u", Precedence::UnOp); - hashmap.insert(b"-w", Precedence::UnOp); - hashmap.insert(b"-x", Precedence::UnOp); - hashmap.insert(b"-z", Precedence::UnOp); - - hashmap.insert(b"=", Precedence::BinOp); - hashmap.insert(b"!=", Precedence::BinOp); - hashmap.insert(b"-eq", Precedence::BinOp); - hashmap.insert(b"-ne", Precedence::BinOp); - hashmap.insert(b"-gt", Precedence::BinOp); - hashmap.insert(b"-ge", Precedence::BinOp); - hashmap.insert(b"-lt", Precedence::BinOp); - hashmap.insert(b"-le", Precedence::BinOp); - - hashmap.insert(b"!", Precedence::BUnOp); - - hashmap.insert(b"-a", Precedence::And); - hashmap.insert(b"-o", Precedence::Or); - - hashmap.insert(b"(", Precedence::Paren); - hashmap.insert(b")", Precedence::Paren); - - hashmap -} - #[derive(Eq, PartialEq)] enum PathCondition { BlockSpecial, @@ -334,14 +177,10 @@ enum PathCondition { } #[cfg(not(windows))] -fn path(path: &[u8], cond: PathCondition) -> bool { - use std::ffi::OsStr; +fn path(path: &OsStr, cond: PathCondition) -> bool { use std::fs::{self, Metadata}; - use std::os::unix::ffi::OsStrExt; use std::os::unix::fs::{FileTypeExt, MetadataExt}; - let path = OsStr::from_bytes(path); - const S_ISUID: u32 = 0o4000; const S_ISGID: u32 = 0o2000; @@ -403,13 +242,14 @@ fn path(path: &[u8], cond: PathCondition) -> bool { } #[cfg(windows)] -fn path(path: &[u8], cond: PathCondition) -> bool { +fn path(path: &OsStr, cond: PathCondition) -> bool { use std::fs::metadata; - let path = from_utf8(path).unwrap(); + let stat = match metadata(path) { Ok(s) => s, _ => return false, }; + match cond { PathCondition::BlockSpecial => false, PathCondition::CharacterSpecial => false, diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index 6c1c0746a..a44f2733c 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -23,11 +23,9 @@ use std::io::{stdin, stdout, BufRead, BufWriter, Write}; use crate::expand::ExpandSet; use uucore::InvalidEncodingHandling; -static NAME: &str = "tr"; static VERSION: &str = env!("CARGO_PKG_VERSION"); static ABOUT: &str = "translate or delete characters"; -static LONG_HELP: &str = "Translate, squeeze, and/or delete characters from standard input, -writing to standard output."; + const BUFFER_LEN: usize = 1024; mod options { @@ -125,10 +123,17 @@ impl SymbolTranslator for DeleteAndSqueezeOperation { struct TranslateOperation { translate_map: FnvHashMap, + complement: bool, + s2_last: char, } impl TranslateOperation { - fn new(set1: ExpandSet, set2: &mut ExpandSet, truncate: bool) -> TranslateOperation { + fn new( + set1: ExpandSet, + set2: &mut ExpandSet, + truncate: bool, + complement: bool, + ) -> TranslateOperation { let mut map = FnvHashMap::default(); let mut s2_prev = '_'; for i in set1 { @@ -141,13 +146,54 @@ impl TranslateOperation { map.insert(i as usize, s2_prev); } } - TranslateOperation { translate_map: map } + TranslateOperation { + translate_map: map, + complement, + s2_last: set2.last().unwrap_or(s2_prev), + } } } impl SymbolTranslator for TranslateOperation { fn translate(&self, c: char, _prev_c: char) -> Option { - Some(*self.translate_map.get(&(c as usize)).unwrap_or(&c)) + if self.complement { + Some(if self.translate_map.contains_key(&(c as usize)) { + c + } else { + self.s2_last + }) + } else { + Some(*self.translate_map.get(&(c as usize)).unwrap_or(&c)) + } + } +} + +struct TranslateAndSqueezeOperation { + translate: TranslateOperation, + squeeze: SqueezeOperation, +} + +impl TranslateAndSqueezeOperation { + fn new( + set1: ExpandSet, + set2: &mut ExpandSet, + set2_: ExpandSet, + truncate: bool, + complement: bool, + ) -> TranslateAndSqueezeOperation { + TranslateAndSqueezeOperation { + translate: TranslateOperation::new(set1, set2, truncate, complement), + squeeze: SqueezeOperation::new(set2_, complement), + } + } +} + +impl SymbolTranslator for TranslateAndSqueezeOperation { + fn translate(&self, c: char, prev_c: char) -> Option { + // `unwrap()` will never panic because `Translate.translate()` + // always returns `Some`. + self.squeeze + .translate(self.translate.translate(c, 0 as char).unwrap(), prev_c) } } @@ -168,8 +214,11 @@ fn translate_input( // isolation to make borrow checker happy let filtered = buf.chars().filter_map(|c| { let res = translator.translate(c, prev_c); - if res.is_some() { - prev_c = c; + // Set `prev_c` to the post-translate character. This + // allows the squeeze operation to correctly function + // after the translate operation. + if let Some(rc) = res { + prev_c = rc; } res }); @@ -186,24 +235,38 @@ fn get_usage() -> String { format!("{} [OPTION]... SET1 [SET2]", executable!()) } +fn get_long_usage() -> String { + String::from( + "Translate, squeeze, and/or delete characters from standard input, +writing to standard output.", + ) +} + pub fn uumain(args: impl uucore::Args) -> i32 { - let usage = get_usage(); let args = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); + let usage = get_usage(); + let after_help = get_long_usage(); + let matches = App::new(executable!()) .version(VERSION) .about(ABOUT) .usage(&usage[..]) - .after_help(LONG_HELP) + .after_help(&after_help[..]) .arg( Arg::with_name(options::COMPLEMENT) - .short("C") + // .visible_short_alias('C') // TODO: requires clap "3.0.0-beta.2" .short("c") .long(options::COMPLEMENT) .help("use the complement of SET1"), ) + .arg( + Arg::with_name("C") // work around for `Arg::visible_short_alias` + .short("C") + .help("same as -c"), + ) .arg( Arg::with_name(options::DELETE) .short("d") @@ -216,8 +279,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .short("s") .help( "replace each sequence of a repeated character that is - listed in the last specified SET, with a single occurrence - of that character", + listed in the last specified SET, with a single occurrence + of that character", ), ) .arg( @@ -230,7 +293,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .get_matches_from(args); let delete_flag = matches.is_present(options::DELETE); - let complement_flag = matches.is_present(options::COMPLEMENT); + let complement_flag = matches.is_present(options::COMPLEMENT) || matches.is_present("C"); let squeeze_flag = matches.is_present(options::SQUEEZE); let truncate_flag = matches.is_present(options::TRUNCATE); @@ -242,7 +305,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { if sets.is_empty() { show_error!( "missing operand\nTry `{} --help` for more information.", - NAME + executable!() ); return 1; } @@ -251,16 +314,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 { show_error!( "missing operand after ‘{}’\nTry `{} --help` for more information.", sets[0], - NAME + executable!() ); return 1; } - if complement_flag && !delete_flag && !squeeze_flag { - show_error!("-c is only supported with -d or -s"); - return 1; - } - let stdin = stdin(); let mut locked_stdin = stdin.lock(); let stdout = stdout(); @@ -278,12 +336,25 @@ pub fn uumain(args: impl uucore::Args) -> i32 { translate_input(&mut locked_stdin, &mut buffered_stdout, op); } } else if squeeze_flag { - let op = SqueezeOperation::new(set1, complement_flag); - translate_input(&mut locked_stdin, &mut buffered_stdout, op); + if sets.len() < 2 { + let op = SqueezeOperation::new(set1, complement_flag); + translate_input(&mut locked_stdin, &mut buffered_stdout, op); + } else { + let mut set2 = ExpandSet::new(sets[1].as_ref()); + let set2_ = ExpandSet::new(sets[1].as_ref()); + let op = TranslateAndSqueezeOperation::new( + set1, + &mut set2, + set2_, + complement_flag, + truncate_flag, + ); + translate_input(&mut locked_stdin, &mut buffered_stdout, op); + } } else { let mut set2 = ExpandSet::new(sets[1].as_ref()); - let op = TranslateOperation::new(set1, &mut set2, truncate_flag); - translate_input(&mut locked_stdin, &mut buffered_stdout, op) + let op = TranslateOperation::new(set1, &mut set2, truncate_flag, complement_flag); + translate_input(&mut locked_stdin, &mut buffered_stdout, op); } 0 diff --git a/src/uu/wc/src/countable.rs b/src/uu/wc/src/countable.rs new file mode 100644 index 000000000..3da910a03 --- /dev/null +++ b/src/uu/wc/src/countable.rs @@ -0,0 +1,72 @@ +//! Traits and implementations for iterating over lines in a file-like object. +//! +//! This module provides a [`WordCountable`] trait and implementations +//! for some common file-like objects. Use the [`WordCountable::lines`] +//! method to get an iterator over lines of a file-like object. +use std::fs::File; +use std::io::{self, BufRead, BufReader, Read, StdinLock}; + +#[cfg(unix)] +use std::os::unix::io::AsRawFd; + +#[cfg(unix)] +pub trait WordCountable: AsRawFd + Read { + type Buffered: BufRead; + fn lines(self) -> Lines; +} + +#[cfg(not(unix))] +pub trait WordCountable: Read { + type Buffered: BufRead; + fn lines(self) -> Lines; +} + +impl WordCountable for StdinLock<'_> { + type Buffered = Self; + + fn lines(self) -> Lines + where + Self: Sized, + { + Lines { buf: self } + } +} +impl WordCountable for File { + type Buffered = BufReader; + + fn lines(self) -> Lines + where + Self: Sized, + { + Lines { + buf: BufReader::new(self), + } + } +} + +/// An iterator over the lines of an instance of `BufRead`. +/// +/// Similar to [`io::Lines`] but yields each line as a `Vec` and +/// includes the newline character (`\n`, the `0xA` byte) that +/// terminates the line. +/// +/// [`io::Lines`]:: io::Lines +pub struct Lines { + buf: B, +} + +impl Iterator for Lines { + type Item = io::Result>; + + fn next(&mut self) -> Option { + let mut line = Vec::new(); + + // reading from a TTY seems to raise a condition on, rather than return Some(0) like a file. + // hence the option wrapped in a result here + match self.buf.read_until(b'\n', &mut line) { + Ok(0) => None, + Ok(_n) => Some(Ok(line)), + Err(e) => Some(Err(e)), + } + } +} diff --git a/src/uu/wc/src/wc.rs b/src/uu/wc/src/wc.rs index 59ca10141..3b70856fa 100644 --- a/src/uu/wc/src/wc.rs +++ b/src/uu/wc/src/wc.rs @@ -11,17 +11,17 @@ extern crate uucore; mod count_bytes; +mod countable; use count_bytes::count_bytes_fast; +use countable::WordCountable; use clap::{App, Arg, ArgMatches}; use thiserror::Error; use std::cmp::max; use std::fs::File; -use std::io::{self, BufRead, BufReader, Read, StdinLock, Write}; +use std::io::{self, Write}; use std::ops::{Add, AddAssign}; -#[cfg(unix)] -use std::os::unix::io::AsRawFd; use std::path::Path; use std::str::from_utf8; @@ -82,32 +82,6 @@ impl Settings { } } -#[cfg(unix)] -trait WordCountable: AsRawFd + Read { - type Buffered: BufRead; - fn get_buffered(self) -> Self::Buffered; -} -#[cfg(not(unix))] -trait WordCountable: Read { - type Buffered: BufRead; - fn get_buffered(self) -> Self::Buffered; -} - -impl WordCountable for StdinLock<'_> { - type Buffered = Self; - - fn get_buffered(self) -> Self::Buffered { - self - } -} -impl WordCountable for File { - type Buffered = BufReader; - - fn get_buffered(self) -> Self::Buffered { - BufReader::new(self) - } -} - #[derive(Debug, Default, Copy, Clone)] struct WordCount { bytes: usize, @@ -270,25 +244,16 @@ fn word_count_from_reader( let mut byte_count: usize = 0; let mut char_count: usize = 0; let mut longest_line_length: usize = 0; - let mut raw_line = Vec::new(); let mut ends_lf: bool; // reading from a TTY seems to raise a condition on, rather than return Some(0) like a file. // hence the option wrapped in a result here - let mut buffered_reader = reader.get_buffered(); - loop { - match buffered_reader.read_until(LF, &mut raw_line) { - Ok(n) => { - if n == 0 { - break; - } - } - Err(ref e) => { - if !raw_line.is_empty() { - show_warning!("Error while reading {}: {}", path, e); - } else { - break; - } + for line_result in reader.lines() { + let raw_line = match line_result { + Ok(l) => l, + Err(e) => { + show_warning!("Error while reading {}: {}", path, e); + continue; } }; @@ -317,8 +282,6 @@ fn word_count_from_reader( longest_line_length = current_char_count - (ends_lf as usize); } } - - raw_line.truncate(0); } Ok(WordCount { diff --git a/src/uu/who/Cargo.toml b/src/uu/who/Cargo.toml index c0cd63795..4d8eccb45 100644 --- a/src/uu/who/Cargo.toml +++ b/src/uu/who/Cargo.toml @@ -17,6 +17,7 @@ path = "src/who.rs" [dependencies] uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["utmpx"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } +clap = "2.33.3" [[bin]] name = "who" diff --git a/src/uu/who/src/who.rs b/src/uu/who/src/who.rs index e979d2d46..ba1360eff 100644 --- a/src/uu/who/src/who.rs +++ b/src/uu/who/src/who.rs @@ -12,79 +12,169 @@ extern crate uucore; use uucore::libc::{ttyname, STDIN_FILENO, S_IWGRP}; use uucore::utmpx::{self, time, Utmpx}; +use clap::{App, Arg}; use std::borrow::Cow; use std::ffi::CStr; use std::os::unix::fs::MetadataExt; use std::path::PathBuf; use uucore::InvalidEncodingHandling; -static SYNTAX: &str = "[OPTION]... [ FILE | ARG1 ARG2 ]"; -static SUMMARY: &str = "Print information about users who are currently logged in."; -static LONG_HELP: &str = " - -a, --all same as -b -d --login -p -r -t -T -u - -b, --boot time of last system boot - -d, --dead print dead processes - -H, --heading print line of column headings - -l, --login print system login processes - --lookup attempt to canonicalize hostnames via DNS - -m only hostname and user associated with stdin - -p, --process print active processes spawned by init - -q, --count all login names and number of users logged on - -r, --runlevel print current runlevel (not available on BSDs) - -s, --short print only name, line, and time (default) - -t, --time print last system clock change - -T, -w, --mesg add user's message status as +, - or ? - -u, --users list users logged in - --message same as -T - --writable same as -T - --help display this help and exit - --version output version information and exit +mod options { + pub const ALL: &str = "all"; + pub const BOOT: &str = "boot"; + pub const DEAD: &str = "dead"; + pub const HEADING: &str = "heading"; + pub const LOGIN: &str = "login"; + pub const LOOKUP: &str = "lookup"; + pub const ONLY_HOSTNAME_USER: &str = "only_hostname_user"; + pub const PROCESS: &str = "process"; + pub const COUNT: &str = "count"; + #[cfg(any(target_vendor = "apple", target_os = "linux", target_os = "android"))] + pub const RUNLEVEL: &str = "runlevel"; + pub const SHORT: &str = "short"; + pub const TIME: &str = "time"; + pub const USERS: &str = "users"; + pub const MESG: &str = "mesg"; // aliases: --message, --writable + pub const FILE: &str = "FILE"; // if length=1: FILE, if length=2: ARG1 ARG2 +} -If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common. -If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual. -"; +static VERSION: &str = env!("CARGO_PKG_VERSION"); +static ABOUT: &str = "Print information about users who are currently logged in."; + +fn get_usage() -> String { + format!("{0} [OPTION]... [ FILE | ARG1 ARG2 ]", executable!()) +} + +fn get_long_usage() -> String { + String::from( + "If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common.\n\ +If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.", + ) +} pub fn uumain(args: impl uucore::Args) -> i32 { let args = args .collect_str(InvalidEncodingHandling::Ignore) .accept_any(); - let mut opts = app!(SYNTAX, SUMMARY, LONG_HELP); - opts.optflag("a", "all", "same as -b -d --login -p -r -t -T -u"); - opts.optflag("b", "boot", "time of last system boot"); - opts.optflag("d", "dead", "print dead processes"); - opts.optflag("H", "heading", "print line of column headings"); - opts.optflag("l", "login", "print system login processes"); - opts.optflag("", "lookup", "attempt to canonicalize hostnames via DNS"); - opts.optflag("m", "", "only hostname and user associated with stdin"); - opts.optflag("p", "process", "print active processes spawned by init"); - opts.optflag( - "q", - "count", - "all login names and number of users logged on", - ); - #[cfg(any(target_vendor = "apple", target_os = "linux", target_os = "android"))] - opts.optflag("r", "runlevel", "print current runlevel"); - opts.optflag("s", "short", "print only name, line, and time (default)"); - opts.optflag("t", "time", "print last system clock change"); - opts.optflag("u", "users", "list users logged in"); - opts.optflag("w", "mesg", "add user's message status as +, - or ?"); - // --message, --writable are the same as --mesg - opts.optflag("T", "message", ""); - opts.optflag("T", "writable", ""); + let usage = get_usage(); + let after_help = get_long_usage(); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .after_help(&after_help[..]) + .arg( + Arg::with_name(options::ALL) + .long(options::ALL) + .short("a") + .help("same as -b -d --login -p -r -t -T -u"), + ) + .arg( + Arg::with_name(options::BOOT) + .long(options::BOOT) + .short("b") + .help("time of last system boot"), + ) + .arg( + Arg::with_name(options::DEAD) + .long(options::DEAD) + .short("d") + .help("print dead processes"), + ) + .arg( + Arg::with_name(options::HEADING) + .long(options::HEADING) + .short("H") + .help("print line of column headings"), + ) + .arg( + Arg::with_name(options::LOGIN) + .long(options::LOGIN) + .short("l") + .help("print system login processes"), + ) + .arg( + Arg::with_name(options::LOOKUP) + .long(options::LOOKUP) + .help("attempt to canonicalize hostnames via DNS"), + ) + .arg( + Arg::with_name(options::ONLY_HOSTNAME_USER) + .short("m") + .help("only hostname and user associated with stdin"), + ) + .arg( + Arg::with_name(options::PROCESS) + .long(options::PROCESS) + .short("p") + .help("print active processes spawned by init"), + ) + .arg( + Arg::with_name(options::COUNT) + .long(options::COUNT) + .short("q") + .help("all login names and number of users logged on"), + ) + .arg( + #[cfg(any(target_vendor = "apple", target_os = "linux", target_os = "android"))] + Arg::with_name(options::RUNLEVEL) + .long(options::RUNLEVEL) + .short("r") + .help("print current runlevel"), + ) + .arg( + Arg::with_name(options::SHORT) + .long(options::SHORT) + .short("s") + .help("print only name, line, and time (default)"), + ) + .arg( + Arg::with_name(options::TIME) + .long(options::TIME) + .short("t") + .help("print last system clock change"), + ) + .arg( + Arg::with_name(options::USERS) + .long(options::USERS) + .short("u") + .help("list users logged in"), + ) + .arg( + Arg::with_name(options::MESG) + .long(options::MESG) + .short("T") + // .visible_short_alias('w') // TODO: requires clap "3.0.0-beta.2" + .visible_aliases(&["message", "writable"]) + .help("add user's message status as +, - or ?"), + ) + .arg( + Arg::with_name("w") // work around for `Arg::visible_short_alias` + .short("w") + .help("same as -T"), + ) + .arg( + Arg::with_name(options::FILE) + .takes_value(true) + .min_values(1) + .max_values(2), + ) + .get_matches_from(args); - let matches = opts.parse(args); + let files: Vec = matches + .values_of(options::FILE) + .map(|v| v.map(ToString::to_string).collect()) + .unwrap_or_default(); // If true, attempt to canonicalize hostnames via a DNS lookup. - let do_lookup = matches.opt_present("lookup"); + let do_lookup = matches.is_present(options::LOOKUP); // If true, display only a list of usernames and count of // the users logged on. // Ignored for 'who am i'. - let short_list = matches.opt_present("q"); + let short_list = matches.is_present(options::COUNT); // If true, display only name, line, and time fields. let mut short_output = false; @@ -95,12 +185,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let mut include_idle = false; // If true, display a line at the top describing each field. - let include_heading = matches.opt_present("H"); + let include_heading = matches.is_present(options::HEADING); // If true, display a '+' for each user if mesg y, a '-' if mesg n, // or a '?' if their tty cannot be statted. - let include_mesg = - matches.opt_present("a") || matches.opt_present("T") || matches.opt_present("w"); + let include_mesg = matches.is_present(options::ALL) + || matches.is_present(options::MESG) + || matches.is_present("w"); // If true, display process termination & exit status. let mut include_exit = false; @@ -133,7 +224,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { #[allow(clippy::useless_let_if_seq)] { - if matches.opt_present("a") { + if matches.is_present(options::ALL) { need_boottime = true; need_deadprocs = true; need_login = true; @@ -146,49 +237,49 @@ pub fn uumain(args: impl uucore::Args) -> i32 { assumptions = false; } - if matches.opt_present("b") { + if matches.is_present(options::BOOT) { need_boottime = true; assumptions = false; } - if matches.opt_present("d") { + if matches.is_present(options::DEAD) { need_deadprocs = true; include_idle = true; include_exit = true; assumptions = false; } - if matches.opt_present("l") { + if matches.is_present(options::LOGIN) { need_login = true; include_idle = true; assumptions = false; } - if matches.opt_present("m") || matches.free.len() == 2 { + if matches.is_present(options::ONLY_HOSTNAME_USER) || files.len() == 2 { my_line_only = true; } - if matches.opt_present("p") { + if matches.is_present(options::PROCESS) { need_initspawn = true; assumptions = false; } - if matches.opt_present("r") { + if matches.is_present(options::RUNLEVEL) { need_runlevel = true; include_idle = true; assumptions = false; } - if matches.opt_present("s") { + if matches.is_present(options::SHORT) { short_output = true; } - if matches.opt_present("t") { + if matches.is_present(options::TIME) { need_clockchange = true; assumptions = false; } - if matches.opt_present("u") { + if matches.is_present(options::USERS) { need_users = true; include_idle = true; assumptions = false; @@ -202,11 +293,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 { if include_exit { short_output = false; } - - if matches.free.len() > 2 { - show_usage_error!("{}", msg_wrong_number_of_arguments!()); - exit!(1); - } } let mut who = Who { @@ -225,7 +311,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { need_runlevel, need_users, my_line_only, - args: matches.free, + args: files, }; who.exec(); diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index 855e64b36..291456760 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -24,7 +24,7 @@ thiserror = { version="1.0", optional=true } lazy_static = { version="1.3", optional=true } nix = { version="<= 0.13", optional=true } platform-info = { version="<= 0.1", optional=true } -time = { version="<= 0.1.42", optional=true } +time = { version="<= 0.1.43", optional=true } # * "problem" dependencies (pinned) data-encoding = { version="~2.1", optional=true } ## data-encoding: require v2.1; but v2.2.0 breaks the build for MinSRV v1.31.0 libc = { version="0.2.15, <= 0.2.85", optional=true } ## libc: initial utmp support added in v0.2.15; but v0.2.68 breaks the build for MinSRV v1.31.0 diff --git a/tests/by-util/test_base32.rs b/tests/by-util/test_base32.rs index 157503d83..fd49aa951 100644 --- a/tests/by-util/test_base32.rs +++ b/tests/by-util/test_base32.rs @@ -98,7 +98,7 @@ fn test_wrap_bad_arg() { .arg(wrap_param) .arg("b") .fails() - .stderr_only("base32: error: invalid wrap size: ‘b’: invalid digit found in string\n"); + .stderr_only("base32: error: Invalid wrap size: ‘b’: invalid digit found in string\n"); } } diff --git a/tests/by-util/test_base64.rs b/tests/by-util/test_base64.rs index 6bc0436c5..8d9dc5639 100644 --- a/tests/by-util/test_base64.rs +++ b/tests/by-util/test_base64.rs @@ -7,6 +7,21 @@ fn test_encode() { .pipe_in(input) .succeeds() .stdout_only("aGVsbG8sIHdvcmxkIQ==\n"); + + // Using '-' as our file + new_ucmd!() + .arg("-") + .pipe_in(input) + .succeeds() + .stdout_only("aGVsbG8sIHdvcmxkIQ==\n"); +} + +#[test] +fn test_base64_encode_file() { + new_ucmd!() + .arg("input-simple.txt") + .succeeds() + .stdout_only("SGVsbG8sIFdvcmxkIQo=\n"); } #[test] @@ -60,10 +75,9 @@ fn test_wrap() { #[test] fn test_wrap_no_arg() { for wrap_param in vec!["-w", "--wrap"] { - new_ucmd!().arg(wrap_param).fails().stderr_only(format!( - "base64: error: Argument to option '{}' missing\n", - if wrap_param == "-w" { "w" } else { "wrap" } - )); + new_ucmd!().arg(wrap_param).fails().stderr_contains( + &"The argument '--wrap ' requires a value but none was supplied", + ); } } @@ -74,6 +88,24 @@ fn test_wrap_bad_arg() { .arg(wrap_param) .arg("b") .fails() - .stderr_only("base64: error: invalid wrap size: ‘b’: invalid digit found in string\n"); + .stderr_only("base64: error: Invalid wrap size: ‘b’: invalid digit found in string\n"); } } + +#[test] +fn test_base64_extra_operand() { + // Expect a failure when multiple files are specified. + new_ucmd!() + .arg("a.txt") + .arg("a.txt") + .fails() + .stderr_only("base64: error: extra operand ‘a.txt’"); +} + +#[test] +fn test_base64_file_not_found() { + new_ucmd!() + .arg("a.txt") + .fails() + .stderr_only("base64: error: a.txt: No such file or directory"); +} diff --git a/tests/by-util/test_basename.rs b/tests/by-util/test_basename.rs index 8d32b4008..2a40ba4b9 100644 --- a/tests/by-util/test_basename.rs +++ b/tests/by-util/test_basename.rs @@ -1,6 +1,29 @@ use crate::common::util::*; use std::ffi::OsStr; +#[test] +fn test_help() { + for help_flg in vec!["-h", "--help"] { + new_ucmd!() + .arg(&help_flg) + .succeeds() + .no_stderr() + .stdout_contains("USAGE:"); + } +} + +#[test] +fn test_version() { + for version_flg in vec!["-V", "--version"] { + assert!(new_ucmd!() + .arg(&version_flg) + .succeeds() + .no_stderr() + .stdout_str() + .starts_with("basename")); + } +} + #[test] fn test_directory() { new_ucmd!() @@ -81,11 +104,25 @@ fn test_no_args() { expect_error(vec![]); } +#[test] +fn test_no_args_output() { + new_ucmd!() + .fails() + .stderr_is("basename: error: missing operand\nTry 'basename --help' for more information."); +} + #[test] fn test_too_many_args() { expect_error(vec!["a", "b", "c"]); } +#[test] +fn test_too_many_args_output() { + new_ucmd!().args(&["a", "b", "c"]).fails().stderr_is( + "basename: error: extra operand 'c'\nTry 'basename --help' for more information.", + ); +} + fn test_invalid_utf8_args(os_str: &OsStr) { let test_vec = vec![os_str.to_os_string()]; new_ucmd!().args(&test_vec).succeeds().stdout_is("fo�o\n"); diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 0ae8d2339..e3b7141d1 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -20,4 +20,16 @@ fn test_df_compatible_si() { new_ucmd!().arg("-aH").succeeds(); } +#[test] +fn test_df_output() { + if cfg!(target_os = "macos") { + new_ucmd!().arg("-H").arg("-total").succeeds(). + stdout_only("Filesystem Size Used Available Capacity Use% Mounted on \n"); + } else { + new_ucmd!().arg("-H").arg("-total").succeeds().stdout_only( + "Filesystem Size Used Available Use% Mounted on \n" + ); + } +} + // ToDO: more tests... diff --git a/tests/by-util/test_dirname.rs b/tests/by-util/test_dirname.rs index bcb4378d6..026ac22bb 100644 --- a/tests/by-util/test_dirname.rs +++ b/tests/by-util/test_dirname.rs @@ -16,6 +16,21 @@ fn test_path_without_trailing_slashes() { .stdout_is("/root/alpha/beta/gamma/delta/epsilon\n"); } +#[test] +fn test_path_without_trailing_slashes_and_zero() { + new_ucmd!() + .arg("-z") + .arg("/root/alpha/beta/gamma/delta/epsilon/omega") + .succeeds() + .stdout_is("/root/alpha/beta/gamma/delta/epsilon\u{0}"); + + new_ucmd!() + .arg("--zero") + .arg("/root/alpha/beta/gamma/delta/epsilon/omega") + .succeeds() + .stdout_is("/root/alpha/beta/gamma/delta/epsilon\u{0}"); +} + #[test] fn test_root() { new_ucmd!().arg("/").run().stdout_is("/\n"); diff --git a/tests/by-util/test_kill.rs b/tests/by-util/test_kill.rs index 651491045..637aea9a2 100644 --- a/tests/by-util/test_kill.rs +++ b/tests/by-util/test_kill.rs @@ -1 +1,126 @@ -// ToDO: add tests +use crate::common::util::*; +use regex::Regex; +use std::os::unix::process::ExitStatusExt; +use std::process::{Child, Command}; + +// A child process the tests will try to kill. +struct Target { + child: Child, + killed: bool, +} + +impl Target { + // Creates a target that will naturally die after some time if not killed + // fast enough. + // This timeout avoids hanging failing tests. + fn new() -> Target { + Target { + child: Command::new("sleep") + .arg("30") + .spawn() + .expect("cannot spawn target"), + killed: false, + } + } + + // Waits for the target to complete and returns the signal it received if any. + fn wait_for_signal(&mut self) -> Option { + let sig = self.child.wait().expect("cannot wait on target").signal(); + self.killed = true; + sig + } + + fn pid(&self) -> u32 { + self.child.id() + } +} + +impl Drop for Target { + // Terminates this target to avoid littering test boxes with zombi processes + // when a test fails after creating a target but before killing it. + fn drop(&mut self) { + if !self.killed { + self.child.kill().expect("cannot kill target"); + } + } +} + +#[test] +fn test_kill_list_all_signals() { + // Check for a few signals. Do not try to be comprehensive. + new_ucmd!() + .arg("-l") + .succeeds() + .stdout_contains("KILL") + .stdout_contains("TERM") + .stdout_contains("HUP"); +} + +#[test] +fn test_kill_list_all_signals_as_table() { + // Check for a few signals. Do not try to be comprehensive. + new_ucmd!() + .arg("-t") + .succeeds() + .stdout_contains("KILL") + .stdout_contains("TERM") + .stdout_contains("HUP"); +} + +#[test] +fn test_kill_list_one_signal_from_name() { + // Use SIGKILL because it is 9 on all unixes. + new_ucmd!() + .arg("-l") + .arg("KILL") + .succeeds() + .stdout_matches(&Regex::new("\\b9\\b").unwrap()); +} + +#[test] +fn test_kill_set_bad_signal_name() { + new_ucmd!() + .arg("-s") + .arg("IAMNOTASIGNAL") + .fails() + .stderr_contains("unknown signal"); +} + +#[test] +fn test_kill_with_default_signal() { + let mut target = Target::new(); + new_ucmd!().arg(format!("{}", target.pid())).succeeds(); + assert_eq!(target.wait_for_signal(), Some(libc::SIGTERM)); +} + +#[test] +fn test_kill_with_signal_number_old_form() { + let mut target = Target::new(); + new_ucmd!() + .arg("-9") + .arg(format!("{}", target.pid())) + .succeeds(); + assert_eq!(target.wait_for_signal(), Some(9)); +} + +#[test] +fn test_kill_with_signal_number_new_form() { + let mut target = Target::new(); + new_ucmd!() + .arg("-s") + .arg("9") + .arg(format!("{}", target.pid())) + .succeeds(); + assert_eq!(target.wait_for_signal(), Some(9)); +} + +#[test] +fn test_kill_with_signal_name_new_form() { + let mut target = Target::new(); + new_ucmd!() + .arg("-s") + .arg("KILL") + .arg(format!("{}", target.pid())) + .succeeds(); + assert_eq!(target.wait_for_signal(), Some(libc::SIGKILL)); +} diff --git a/tests/by-util/test_link.rs b/tests/by-util/test_link.rs index 381ea168a..99559a7fe 100644 --- a/tests/by-util/test_link.rs +++ b/tests/by-util/test_link.rs @@ -39,3 +39,25 @@ fn test_link_nonexistent_file() { assert!(!at.file_exists(file)); assert!(!at.file_exists(link)); } + +#[test] +fn test_link_one_argument() { + let (_, mut ucmd) = at_and_ucmd!(); + let file = "test_link_argument"; + ucmd.args(&[file]).fails().stderr_contains( + "error: The argument '...' requires at least 2 values, but only 1 was provide", + ); +} + +#[test] +fn test_link_three_arguments() { + let (_, mut ucmd) = at_and_ucmd!(); + let arguments = vec![ + "test_link_argument1", + "test_link_argument2", + "test_link_argument3", + ]; + ucmd.args(&arguments[..]).fails().stderr_contains( + format!("error: The value '{}' was provided to '...', but it wasn't expecting any more values", arguments[2]), + ); +} diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 1a3bdf78a..110764aa5 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -43,23 +43,74 @@ fn test_ls_a() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; at.touch(".test-1"); + at.mkdir("some-dir"); + at.touch( + Path::new("some-dir") + .join(".test-2") + .as_os_str() + .to_str() + .unwrap(), + ); - let result = scene.ucmd().succeeds(); - let stdout = result.stdout_str(); - assert!(!stdout.contains(".test-1")); - assert!(!stdout.contains("..")); + let re_pwd = Regex::new(r"^\.\n").unwrap(); + + // Using the present working directory + scene + .ucmd() + .arg("-1") + .succeeds() + .stdout_does_not_contain(".test-1") + .stdout_does_not_contain("..") + .stdout_does_not_match(&re_pwd); scene .ucmd() .arg("-a") + .arg("-1") .succeeds() .stdout_contains(&".test-1") - .stdout_contains(&".."); + .stdout_contains(&"..") + .stdout_matches(&re_pwd); - let result = scene.ucmd().arg("-A").succeeds(); - result.stdout_contains(".test-1"); - let stdout = result.stdout_str(); - assert!(!stdout.contains("..")); + scene + .ucmd() + .arg("-A") + .arg("-1") + .succeeds() + .stdout_contains(".test-1") + .stdout_does_not_contain("..") + .stdout_does_not_match(&re_pwd); + + // Using a subdirectory + scene + .ucmd() + .arg("-1") + .arg("some-dir") + .succeeds() + .stdout_does_not_contain(".test-2") + .stdout_does_not_contain("..") + .stdout_does_not_match(&re_pwd); + + scene + .ucmd() + .arg("-a") + .arg("-1") + .arg("some-dir") + .succeeds() + .stdout_contains(&".test-2") + .stdout_contains(&"..") + .no_stderr() + .stdout_matches(&re_pwd); + + scene + .ucmd() + .arg("-A") + .arg("-1") + .arg("some-dir") + .succeeds() + .stdout_contains(".test-2") + .stdout_does_not_contain("..") + .stdout_does_not_match(&re_pwd); } #[test] @@ -482,7 +533,6 @@ fn test_ls_sort_name() { .succeeds() .stdout_is(["test-1", "test-2", "test-3\n"].join(sep)); - // Order of a named sort ignores leading dots. let scene_dot = TestScenario::new(util_name!()); let at = &scene_dot.fixtures; at.touch(".a"); @@ -495,7 +545,7 @@ fn test_ls_sort_name() { .arg("--sort=name") .arg("-A") .succeeds() - .stdout_is([".a", "a", ".b", "b\n"].join(sep)); + .stdout_is([".a", ".b", "a", "b\n"].join(sep)); } #[test] @@ -558,6 +608,113 @@ fn test_ls_long_ctime() { } } +#[test] +#[ignore] +fn test_ls_order_birthtime() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + + /* + Here we make 2 files with a timeout in between. + After creating the first file try to sync it. + This ensures the file gets created immediately instead of being saved + inside the OS's IO operation buffer. + Without this, both files might accidentally be created at the same time. + */ + at.make_file("test-birthtime-1").sync_all().unwrap(); + at.make_file("test-birthtime-2").sync_all().unwrap(); + at.open("test-birthtime-1"); + + let result = scene.ucmd().arg("--time=birth").arg("-t").run(); + + #[cfg(not(windows))] + assert_eq!(result.stdout_str(), "test-birthtime-2\ntest-birthtime-1\n"); + #[cfg(windows)] + assert_eq!(result.stdout_str(), "test-birthtime-2 test-birthtime-1\n"); +} + +#[test] +fn test_ls_styles() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + at.touch("test"); + + let re_full = Regex::new( + r"[a-z-]* \d* \w* \w* \d* \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d* \+\d{4} test\n", + ) + .unwrap(); + let re_long = + Regex::new(r"[a-z-]* \d* \w* \w* \d* \d{4}-\d{2}-\d{2} \d{2}:\d{2} test\n").unwrap(); + let re_iso = Regex::new(r"[a-z-]* \d* \w* \w* \d* \d{2}-\d{2} \d{2}:\d{2} test\n").unwrap(); + let re_locale = + Regex::new(r"[a-z-]* \d* \w* \w* \d* [A-Z][a-z]{2} ( |\d)\d \d{2}:\d{2} test\n").unwrap(); + + //full-iso + let result = scene + .ucmd() + .arg("-l") + .arg("--time-style=full-iso") + .succeeds(); + assert!(re_full.is_match(&result.stdout_str())); + //long-iso + let result = scene + .ucmd() + .arg("-l") + .arg("--time-style=long-iso") + .succeeds(); + assert!(re_long.is_match(&result.stdout_str())); + //iso + let result = scene.ucmd().arg("-l").arg("--time-style=iso").succeeds(); + assert!(re_iso.is_match(&result.stdout_str())); + //locale + let result = scene.ucmd().arg("-l").arg("--time-style=locale").succeeds(); + assert!(re_locale.is_match(&result.stdout_str())); + + //Overwrite options tests + let result = scene + .ucmd() + .arg("-l") + .arg("--time-style=long-iso") + .arg("--time-style=iso") + .succeeds(); + assert!(re_iso.is_match(&result.stdout_str())); + let result = scene + .ucmd() + .arg("--time-style=iso") + .arg("--full-time") + .succeeds(); + assert!(re_full.is_match(&result.stdout_str())); + let result = scene + .ucmd() + .arg("--full-time") + .arg("--time-style=iso") + .succeeds(); + assert!(re_iso.is_match(&result.stdout_str())); + + let result = scene + .ucmd() + .arg("--full-time") + .arg("--time-style=iso") + .arg("--full-time") + .succeeds(); + assert!(re_full.is_match(&result.stdout_str())); + + let result = scene + .ucmd() + .arg("--full-time") + .arg("-x") + .arg("-l") + .succeeds(); + assert!(re_full.is_match(&result.stdout_str())); + + at.touch("test2"); + let result = scene.ucmd().arg("--full-time").arg("-x").succeeds(); + #[cfg(not(windows))] + assert_eq!(result.stdout_str(), "test\ntest2\n"); + #[cfg(windows)] + assert_eq!(result.stdout_str(), "test test2\n"); +} + #[test] fn test_ls_order_time() { let scene = TestScenario::new(util_name!()); diff --git a/tests/by-util/test_pinky.rs b/tests/by-util/test_pinky.rs index 7a4a3f3df..1a7ef8b61 100644 --- a/tests/by-util/test_pinky.rs +++ b/tests/by-util/test_pinky.rs @@ -34,6 +34,36 @@ fn test_long_format() { )); } +#[cfg(target_os = "linux")] +#[test] +fn test_long_format_multiple_users() { + let scene = TestScenario::new(util_name!()); + + let expected = scene + .cmd_keepenv(util_name!()) + .env("LANGUAGE", "C") + .arg("-l") + .arg("root") + .arg("root") + .arg("root") + .succeeds(); + + scene + .ucmd() + .arg("-l") + .arg("root") + .arg("root") + .arg("root") + .succeeds() + .stdout_is(expected.stdout_str()); +} + +#[test] +fn test_long_format_wo_user() { + // "no username specified; at least one must be specified when using -l" + new_ucmd!().arg("-l").fails().code_is(1); +} + #[cfg(target_os = "linux")] #[test] fn test_short_format_i() { diff --git a/tests/by-util/test_relpath.rs b/tests/by-util/test_relpath.rs index cc17b45c3..5094d25a8 100644 --- a/tests/by-util/test_relpath.rs +++ b/tests/by-util/test_relpath.rs @@ -103,7 +103,7 @@ fn test_relpath_with_from_with_d() { at.mkdir_all(from); // d is part of subpath -> expect relative path - let mut result_stdout = scene + let mut _result_stdout = scene .ucmd() .arg(to) .arg(from) @@ -112,17 +112,17 @@ fn test_relpath_with_from_with_d() { .stdout_move_str(); // relax rules for windows test environment #[cfg(not(windows))] - assert!(Path::new(&result_stdout).is_relative()); + assert!(Path::new(&_result_stdout).is_relative()); // d is not part of subpath -> expect absolut path - result_stdout = scene + _result_stdout = scene .ucmd() .arg(to) .arg(from) .arg("-dnon_existing") .succeeds() .stdout_move_str(); - assert!(Path::new(&result_stdout).is_absolute()); + assert!(Path::new(&_result_stdout).is_absolute()); } } @@ -135,12 +135,12 @@ fn test_relpath_no_from_no_d() { let to: &str = &convert_path(test.to); at.mkdir_all(to); - let result_stdout = scene.ucmd().arg(to).succeeds().stdout_move_str(); + let _result_stdout = scene.ucmd().arg(to).succeeds().stdout_move_str(); #[cfg(not(windows))] - assert_eq!(result_stdout, format!("{}\n", to)); + assert_eq!(_result_stdout, format!("{}\n", to)); // relax rules for windows test environment #[cfg(windows)] - assert!(result_stdout.ends_with(&format!("{}\n", to))); + assert!(_result_stdout.ends_with(&format!("{}\n", to))); } } diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index 48a5cf36d..eac9490a5 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -15,6 +15,31 @@ fn test_helper(file_name: &str, args: &str) { .stdout_is_fixture(format!("{}.expected.debug", file_name)); } +// FYI, the initialization size of our Line struct is 96 bytes. +// +// At very small buffer sizes, with that overhead we are certainly going +// to overrun our buffer way, way, way too quickly because of these excess +// bytes for the struct. +// +// For instance, seq 0..20000 > ...text = 108894 bytes +// But overhead is 1920000 + 108894 = 2028894 bytes +// +// Or kjvbible-random.txt = 4332506 bytes, but minimum size of its +// 99817 lines in memory * 96 bytes = 9582432 bytes +// +// Here, we test 108894 bytes with a 50K buffer +// +#[test] +fn test_larger_than_specified_segment() { + new_ucmd!() + .arg("-n") + .arg("-S") + .arg("50K") + .arg("ext_sort.txt") + .succeeds() + .stdout_is_fixture(format!("{}", "ext_sort.expected")); +} + #[test] fn test_months_whitespace() { test_helper("months-whitespace", "-M"); @@ -34,6 +59,18 @@ fn test_human_numeric_whitespace() { test_helper("human-numeric-whitespace", "-h"); } +// This tests where serde often fails when reading back JSON +// if it finds a null value +#[test] +fn test_extsort_as64_bailout() { + new_ucmd!() + .arg("-g") + .arg("-S 5K") + .arg("multiple_decimals_general.txt") + .succeeds() + .stdout_is_fixture("multiple_decimals_general.expected"); +} + #[test] fn test_multiple_decimals_general() { test_helper("multiple_decimals_general", "-g") diff --git a/tests/by-util/test_test.rs b/tests/by-util/test_test.rs index 4b9a9ff55..000013d9c 100644 --- a/tests/by-util/test_test.rs +++ b/tests/by-util/test_test.rs @@ -2,6 +2,7 @@ // This file is part of the uutils coreutils package. // // (c) mahkoh (ju.orth [at] gmail [dot] com) +// (c) Daniel Rocco // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. @@ -9,11 +10,466 @@ use crate::common::util::*; +#[test] +fn test_empty_test_equivalent_to_false() { + new_ucmd!().run().status_code(1); +} + +#[test] +fn test_empty_string_is_false() { + new_ucmd!().arg("").run().status_code(1); +} + +#[test] +fn test_solo_not() { + new_ucmd!().arg("!").succeeds(); +} + +#[test] +fn test_solo_and_or_or_is_a_literal() { + // /bin/test '' -a '' => 1; so test(1) must interpret `-a` by itself as + // a literal string + new_ucmd!().arg("-a").succeeds(); + new_ucmd!().arg("-o").succeeds(); +} + +#[test] +fn test_double_not_is_false() { + new_ucmd!().args(&["!", "!"]).run().status_code(1); +} + +#[test] +fn test_and_not_is_false() { + new_ucmd!().args(&["-a", "!"]).run().status_code(1); +} + +#[test] +fn test_not_and_is_false() { + // `-a` is a literal here & has nonzero length + new_ucmd!().args(&["!", "-a"]).run().status_code(1); +} + +#[test] +fn test_not_and_not_succeeds() { + new_ucmd!().args(&["!", "-a", "!"]).succeeds(); +} + +#[test] +fn test_simple_or() { + new_ucmd!().args(&["foo", "-o", ""]).succeeds(); +} + +#[test] +fn test_negated_or() { + new_ucmd!() + .args(&["!", "foo", "-o", "bar"]) + .run() + .status_code(1); + new_ucmd!().args(&["foo", "-o", "!", "bar"]).succeeds(); + new_ucmd!() + .args(&["!", "foo", "-o", "!", "bar"]) + .run() + .status_code(1); +} + +#[test] +fn test_strlen_of_nothing() { + // odd but matches GNU, which must interpret -n as a literal here + new_ucmd!().arg("-n").succeeds(); +} + +#[test] +fn test_strlen_of_empty() { + new_ucmd!().args(&["-n", ""]).run().status_code(1); + + // STRING equivalent to -n STRING + new_ucmd!().arg("").run().status_code(1); +} + +#[test] +fn test_nothing_is_empty() { + // -z is a literal here and has nonzero length + new_ucmd!().arg("-z").succeeds(); +} + +#[test] +fn test_zero_len_of_empty() { + new_ucmd!().args(&["-z", ""]).succeeds(); +} + +#[test] +fn test_solo_paren_is_literal() { + let scenario = TestScenario::new(util_name!()); + let tests = [["("], [")"]]; + + for test in &tests { + scenario.ucmd().args(&test[..]).succeeds(); + } +} + +#[test] +fn test_solo_empty_parenthetical_is_error() { + new_ucmd!().args(&["(", ")"]).run().status_code(2); +} + +#[test] +fn test_zero_len_equals_zero_len() { + new_ucmd!().args(&["", "=", ""]).succeeds(); +} + +#[test] +fn test_zero_len_not_equals_zero_len_is_false() { + new_ucmd!().args(&["", "!=", ""]).run().status_code(1); +} + +#[test] +fn test_string_comparison() { + let scenario = TestScenario::new(util_name!()); + let tests = [ + ["foo", "!=", "bar"], + ["contained\nnewline", "=", "contained\nnewline"], + ["(", "=", "("], + ["(", "!=", ")"], + ["!", "=", "!"], + ]; + + for test in &tests { + scenario.ucmd().args(&test[..]).succeeds(); + } +} + +#[test] +#[ignore = "fixme: error reporting"] +fn test_dangling_string_comparison_is_error() { + new_ucmd!() + .args(&["missing_something", "="]) + .run() + .status_code(2) + .stderr_is("test: missing argument after ‘=’"); +} + +#[test] +fn test_stringop_is_literal_after_bang() { + let scenario = TestScenario::new(util_name!()); + let tests = [ + ["!", "="], + ["!", "!="], + ["!", "-eq"], + ["!", "-ne"], + ["!", "-lt"], + ["!", "-le"], + ["!", "-gt"], + ["!", "-ge"], + ["!", "-ef"], + ["!", "-nt"], + ["!", "-ot"], + ]; + + for test in &tests { + scenario.ucmd().args(&test[..]).run().status_code(1); + } +} + +#[test] +fn test_a_bunch_of_not() { + new_ucmd!() + .args(&["!", "", "!=", "", "-a", "!", "", "!=", ""]) + .succeeds(); +} + +#[test] +fn test_pseudofloat_equal() { + new_ucmd!().args(&["123.45", "=", "123.45"]).succeeds(); +} + +#[test] +fn test_pseudofloat_not_equal() { + new_ucmd!().args(&["123.45", "!=", "123.450"]).succeeds(); +} + +#[test] +fn test_negative_arg_is_a_string() { + new_ucmd!().arg("-12345").succeeds(); + new_ucmd!().arg("--qwert").succeeds(); +} + +#[test] +fn test_some_int_compares() { + let scenario = TestScenario::new(util_name!()); + + let tests = [ + ["0", "-eq", "0"], + ["0", "-ne", "1"], + ["421", "-lt", "3720"], + ["0", "-le", "0"], + ["11", "-gt", "10"], + ["1024", "-ge", "512"], + ["9223372036854775806", "-le", "9223372036854775807"], + ]; + + for test in &tests { + scenario.ucmd().args(&test[..]).succeeds(); + } +} + +#[test] +#[ignore = "fixme: evaluation error (code 1); GNU returns 0"] +fn test_values_greater_than_i64_allowed() { + new_ucmd!() + .args(&["9223372036854775808", "-gt", "0"]) + .succeeds(); +} + +#[test] +fn test_negative_int_compare() { + let scenario = TestScenario::new(util_name!()); + + let tests = [ + ["-1", "-eq", "-1"], + ["-1", "-ne", "-2"], + ["-3720", "-lt", "-421"], + ["-10", "-le", "-10"], + ["-21", "-gt", "-22"], + ["-128", "-ge", "-256"], + ["-9223372036854775808", "-le", "-9223372036854775807"], + ]; + + for test in &tests { + scenario.ucmd().args(&test[..]).succeeds(); + } +} + +#[test] +fn test_float_inequality_is_error() { + new_ucmd!() + .args(&["123.45", "-ge", "6"]) + .run() + .status_code(2) + .stderr_is("test: invalid integer ‘123.45’"); +} + +#[test] +#[cfg(not(windows))] +fn test_invalid_utf8_integer_compare() { + use std::ffi::OsStr; + use std::os::unix::ffi::OsStrExt; + + let source = [0x66, 0x6f, 0x80, 0x6f]; + let arg = OsStr::from_bytes(&source[..]); + + let mut cmd = new_ucmd!(); + cmd.arg("123").arg("-ne"); + cmd.raw.arg(arg); + + cmd.run() + .status_code(2) + .stderr_is("test: invalid integer ‘fo�o’"); + + let mut cmd = new_ucmd!(); + cmd.raw.arg(arg); + cmd.arg("-eq").arg("456"); + + cmd.run() + .status_code(2) + .stderr_is("test: invalid integer ‘fo�o’"); +} + +#[test] +#[ignore = "fixme: parse/evaluation error (code 2); GNU returns 1"] +fn test_file_is_itself() { + new_ucmd!() + .args(&["regular_file", "-ef", "regular_file"]) + .succeeds(); +} + +#[test] +#[ignore = "fixme: parse/evaluation error (code 2); GNU returns 1"] +fn test_file_is_newer_than_and_older_than_itself() { + // odd but matches GNU + new_ucmd!() + .args(&["regular_file", "-nt", "regular_file"]) + .run() + .status_code(1); + new_ucmd!() + .args(&["regular_file", "-ot", "regular_file"]) + .run() + .status_code(1); +} + +#[test] +#[ignore = "todo: implement these"] +fn test_newer_file() { + let scenario = TestScenario::new(util_name!()); + + scenario.cmd("touch").arg("newer_file").succeeds(); + scenario + .cmd("touch") + .args(&["-m", "-d", "last Thursday", "regular_file"]) + .succeeds(); + + scenario + .ucmd() + .args(&["newer_file", "-nt", "regular_file"]) + .succeeds(); + scenario + .ucmd() + .args(&["regular_file", "-ot", "newer_file"]) + .succeeds(); +} + +#[test] +fn test_file_exists() { + new_ucmd!().args(&["-e", "regular_file"]).succeeds(); +} + +#[test] +fn test_nonexistent_file_does_not_exist() { + new_ucmd!() + .args(&["-e", "nonexistent_file"]) + .run() + .status_code(1); +} + +#[test] +fn test_nonexistent_file_is_not_regular() { + new_ucmd!() + .args(&["-f", "nonexistent_file"]) + .run() + .status_code(1); +} + +#[test] +fn test_file_exists_and_is_regular() { + new_ucmd!().args(&["-f", "regular_file"]).succeeds(); +} + +#[test] +#[cfg(not(windows))] // FIXME: implement on Windows +fn test_file_is_readable() { + new_ucmd!().args(&["-r", "regular_file"]).succeeds(); +} + +#[test] +#[cfg(not(windows))] // FIXME: implement on Windows +fn test_file_is_not_readable() { + let scenario = TestScenario::new(util_name!()); + let mut ucmd = scenario.ucmd(); + let mut chmod = scenario.cmd("chmod"); + + scenario.fixtures.touch("crypto_file"); + chmod.args(&["u-r", "crypto_file"]).succeeds(); + + ucmd.args(&["!", "-r", "crypto_file"]).succeeds(); +} + +#[test] +#[cfg(not(windows))] // FIXME: implement on Windows +fn test_file_is_writable() { + new_ucmd!().args(&["-w", "regular_file"]).succeeds(); +} + +#[test] +#[cfg(not(windows))] // FIXME: implement on Windows +fn test_file_is_not_writable() { + let scenario = TestScenario::new(util_name!()); + let mut ucmd = scenario.ucmd(); + let mut chmod = scenario.cmd("chmod"); + + scenario.fixtures.touch("immutable_file"); + chmod.args(&["u-w", "immutable_file"]).succeeds(); + + ucmd.args(&["!", "-w", "immutable_file"]).succeeds(); +} + +#[test] +fn test_file_is_not_executable() { + new_ucmd!().args(&["!", "-x", "regular_file"]).succeeds(); +} + +#[test] +#[cfg(not(windows))] // FIXME: implement on Windows +fn test_file_is_executable() { + let scenario = TestScenario::new(util_name!()); + let mut chmod = scenario.cmd("chmod"); + + chmod.args(&["u+x", "regular_file"]).succeeds(); + + scenario.ucmd().args(&["-x", "regular_file"]).succeeds(); +} + +#[test] +fn test_is_not_empty() { + new_ucmd!().args(&["-s", "non_empty_file"]).succeeds(); +} + +#[test] +fn test_nonexistent_file_size_test_is_false() { + new_ucmd!() + .args(&["-s", "nonexistent_file"]) + .run() + .status_code(1); +} + +#[test] +fn test_not_is_not_empty() { + new_ucmd!().args(&["!", "-s", "regular_file"]).succeeds(); +} + +#[test] +#[cfg(not(windows))] +fn test_symlink_is_symlink() { + let scenario = TestScenario::new(util_name!()); + let mut ln = scenario.cmd("ln"); + + // creating symlinks requires admin on Windows + ln.args(&["-s", "regular_file", "symlink"]).succeeds(); + + // FIXME: implement on Windows + scenario.ucmd().args(&["-h", "symlink"]).succeeds(); + scenario.ucmd().args(&["-L", "symlink"]).succeeds(); +} + +#[test] +fn test_file_is_not_symlink() { + let scenario = TestScenario::new(util_name!()); + + scenario + .ucmd() + .args(&["!", "-h", "regular_file"]) + .succeeds(); + scenario + .ucmd() + .args(&["!", "-L", "regular_file"]) + .succeeds(); +} + +#[test] +fn test_nonexistent_file_is_not_symlink() { + let scenario = TestScenario::new(util_name!()); + + scenario + .ucmd() + .args(&["!", "-h", "nonexistent_file"]) + .succeeds(); + scenario + .ucmd() + .args(&["!", "-L", "nonexistent_file"]) + .succeeds(); +} + #[test] fn test_op_prec_and_or_1() { new_ucmd!().args(&[" ", "-o", "", "-a", ""]).succeeds(); } +#[test] +fn test_op_prec_and_or_1_overridden_by_parentheses() { + new_ucmd!() + .args(&["(", " ", "-o", "", ")", "-a", ""]) + .run() + .status_code(1); +} + #[test] fn test_op_prec_and_or_2() { new_ucmd!() @@ -22,6 +478,54 @@ fn test_op_prec_and_or_2() { } #[test] -fn test_or_as_filename() { - new_ucmd!().args(&["x", "-a", "-z", "-o"]).fails(); +fn test_op_prec_and_or_2_overridden_by_parentheses() { + new_ucmd!() + .args(&["", "-a", "(", "", "-o", " ", ")", "-a", " "]) + .run() + .status_code(1); +} + +#[test] +#[ignore = "fixme: error reporting"] +fn test_dangling_parenthesis() { + new_ucmd!() + .args(&["(", "(", "a", "!=", "b", ")", "-o", "-n", "c"]) + .run() + .status_code(2); + new_ucmd!() + .args(&["(", "(", "a", "!=", "b", ")", "-o", "-n", "c", ")"]) + .succeeds(); +} + +#[test] +fn test_complicated_parenthesized_expression() { + new_ucmd!() + .args(&[ + "(", "(", "!", "(", "a", "=", "b", ")", "-o", "c", "=", "d", ")", "-a", "(", "q", "!=", + "r", ")", ")", + ]) + .succeeds(); +} + +#[test] +fn test_erroneous_parenthesized_expression() { + new_ucmd!() + .args(&["a", "!=", "(", "b", "-a", "b", ")", "!=", "c"]) + .run() + .status_code(2) + .stderr_is("test: extra argument ‘b’"); +} + +#[test] +fn test_or_as_filename() { + new_ucmd!() + .args(&["x", "-a", "-z", "-o"]) + .run() + .status_code(1); +} + +#[test] +#[ignore = "GNU considers this an error"] +fn test_strlen_and_nothing() { + new_ucmd!().args(&["-n", "a", "-a"]).run().status_code(2); } diff --git a/tests/by-util/test_tr.rs b/tests/by-util/test_tr.rs index 630c305c6..29712b44a 100644 --- a/tests/by-util/test_tr.rs +++ b/tests/by-util/test_tr.rs @@ -45,6 +45,70 @@ fn test_delete_complement() { .stdout_is("ac"); } +#[test] +fn test_delete_complement_2() { + new_ucmd!() + .args(&["-d", "-C", "0-9"]) + .pipe_in("Phone: 01234 567890") + .succeeds() + .stdout_is("01234567890"); + new_ucmd!() + .args(&["-d", "--complement", "0-9"]) + .pipe_in("Phone: 01234 567890") + .succeeds() + .stdout_is("01234567890"); +} + +#[test] +fn test_complement1() { + new_ucmd!() + .args(&["-c", "a", "X"]) + .pipe_in("ab") + .run() + .stdout_is("aX"); +} + +#[test] +fn test_complement2() { + new_ucmd!() + .args(&["-c", "0-9", "x"]) + .pipe_in("Phone: 01234 567890") + .run() + .stdout_is("xxxxxxx01234x567890"); +} + +#[test] +fn test_complement3() { + new_ucmd!() + .args(&["-c", "abcdefgh", "123"]) + .pipe_in("the cat and the bat") + .run() + .stdout_is("3he3ca33a3d33he3ba3"); +} + +#[test] +fn test_complement4() { + // $ echo -n '0x1y2z3' | tr -c '0-@' '*-~' + // 0~1~2~3 + new_ucmd!() + .args(&["-c", "0-@", "*-~"]) + .pipe_in("0x1y2z3") + .run() + .stdout_is("0~1~2~3"); +} + +#[test] +#[ignore = "fixme: GNU tr returns '0a1b2c3' instead of '0~1~2~3', see #2158"] +fn test_complement5() { + // $ echo '0x1y2z3' | tr -c '\0-@' '*-~' + // 0a1b2c3 + new_ucmd!() + .args(&["-c", "\\0-@", "*-~"]) + .pipe_in("0x1y2z3") + .run() + .stdout_is("0a1b2c3"); +} + #[test] fn test_squeeze() { new_ucmd!() @@ -63,6 +127,24 @@ fn test_squeeze_complement() { .stdout_is("aaBcDcc"); } +#[test] +fn test_translate_and_squeeze() { + new_ucmd!() + .args(&["-s", "x", "y"]) + .pipe_in("xx") + .run() + .stdout_is("y"); +} + +#[test] +fn test_translate_and_squeeze_multiple_lines() { + new_ucmd!() + .args(&["-s", "x", "y"]) + .pipe_in("xxaax\nxaaxx") + .run() + .stdout_is("yaay\nyaay"); +} + #[test] fn test_delete_and_squeeze() { new_ucmd!() diff --git a/tests/by-util/test_truncate.rs b/tests/by-util/test_truncate.rs index d524c096f..8f88f4c74 100644 --- a/tests/by-util/test_truncate.rs +++ b/tests/by-util/test_truncate.rs @@ -224,8 +224,14 @@ fn test_size_and_reference() { let mut file1 = at.make_file(TFILE1); let mut file2 = at.make_file(TFILE2); file1.write_all(b"1234567890").unwrap(); - ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2]).succeeds(); + ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2]) + .succeeds(); file2.seek(SeekFrom::End(0)).unwrap(); let actual = file2.seek(SeekFrom::Current(0)).unwrap(); - assert!(expected == actual, "expected '{}' got '{}'", expected, actual); + assert!( + expected == actual, + "expected '{}' got '{}'", + expected, + actual + ); } diff --git a/tests/by-util/test_uname.rs b/tests/by-util/test_uname.rs index 6b8d2d59d..da901d985 100644 --- a/tests/by-util/test_uname.rs +++ b/tests/by-util/test_uname.rs @@ -36,7 +36,12 @@ fn test_uname_kernel_version() { fn test_uname_kernel() { let (_, mut ucmd) = at_and_ucmd!(); - let result = ucmd.arg("-o").succeeds(); #[cfg(target_os = "linux")] - assert!(result.stdout_str().to_lowercase().contains("linux")); + { + let result = ucmd.arg("-o").succeeds(); + assert!(result.stdout_str().to_lowercase().contains("linux")); + } + + #[cfg(not(target_os = "linux"))] + let result = ucmd.arg("-o").succeeds(); } diff --git a/tests/by-util/test_wc.rs b/tests/by-util/test_wc.rs index 075878470..a16f1854e 100644 --- a/tests/by-util/test_wc.rs +++ b/tests/by-util/test_wc.rs @@ -112,3 +112,60 @@ fn test_multiple_default() { alice_in_wonderland.txt\n 36 370 2189 total\n", ); } + +/// Test for an empty file. +#[test] +fn test_file_empty() { + // TODO There is a leading space in the output that should be + // removed; see issue #2173. + new_ucmd!() + .args(&["-clmwL", "emptyfile.txt"]) + .run() + .stdout_is(" 0 0 0 0 0 emptyfile.txt\n"); +} + +/// Test for an file containing a single non-whitespace character +/// *without* a trailing newline. +#[test] +fn test_file_single_line_no_trailing_newline() { + // TODO There is a leading space in the output that should be + // removed; see issue #2173. + new_ucmd!() + .args(&["-clmwL", "notrailingnewline.txt"]) + .run() + .stdout_is(" 1 1 2 2 1 notrailingnewline.txt\n"); +} + +/// Test for a file that has 100 empty lines (that is, the contents of +/// the file are the newline character repeated one hundred times). +#[test] +fn test_file_many_empty_lines() { + // TODO There is a leading space in the output that should be + // removed; see issue #2173. + new_ucmd!() + .args(&["-clmwL", "manyemptylines.txt"]) + .run() + .stdout_is(" 100 0 100 100 0 manyemptylines.txt\n"); +} + +/// Test for a file that has one long line comprising only spaces. +#[test] +fn test_file_one_long_line_only_spaces() { + // TODO There is a leading space in the output that should be + // removed; see issue #2173. + new_ucmd!() + .args(&["-clmwL", "onelongemptyline.txt"]) + .run() + .stdout_is(" 1 0 10001 10001 10000 onelongemptyline.txt\n"); +} + +/// Test for a file that has one long line comprising a single "word". +#[test] +fn test_file_one_long_word() { + // TODO There is a leading space in the output that should be + // removed; see issue #2173. + new_ucmd!() + .args(&["-clmwL", "onelongword.txt"]) + .run() + .stdout_is(" 1 1 10001 10001 10000 onelongword.txt\n"); +} diff --git a/tests/by-util/test_who.rs b/tests/by-util/test_who.rs index 32d2427e0..a5637f23a 100644 --- a/tests/by-util/test_who.rs +++ b/tests/by-util/test_who.rs @@ -1,11 +1,13 @@ -#[cfg(target_os = "linux")] use crate::common::util::*; #[cfg(target_os = "linux")] #[test] fn test_count() { for opt in vec!["-q", "--count"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } @@ -13,17 +15,21 @@ fn test_count() { #[test] fn test_boot() { for opt in vec!["-b", "--boot"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } #[cfg(target_os = "linux")] #[test] fn test_heading() { - for opt in vec!["-H"] { + for opt in vec!["-H", "--heading"] { // allow whitespace variation - // * minor whitespace differences occur between platform built-in outputs; specifically number of TABs between "TIME" and "COMMENT" may be variant - let actual = new_ucmd!().arg(opt).run().stdout_move_str(); + // * minor whitespace differences occur between platform built-in outputs; + // specifically number of TABs between "TIME" and "COMMENT" may be variant + let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str(); let expect = expected_result(opt); println!("actual: {:?}", actual); println!("expect: {:?}", expect); @@ -37,7 +43,10 @@ fn test_heading() { #[test] fn test_short() { for opt in vec!["-s", "--short"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } @@ -45,7 +54,10 @@ fn test_short() { #[test] fn test_login() { for opt in vec!["-l", "--login"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } @@ -53,7 +65,109 @@ fn test_login() { #[test] fn test_m() { for opt in vec!["-m"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn test_process() { + for opt in vec!["-p", "--process"] { + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn test_runlevel() { + for opt in vec!["-r", "--runlevel"] { + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn test_time() { + for opt in vec!["-t", "--time"] { + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn test_mesg() { + for opt in vec!["-w", "-T", "--users", "--message", "--writable"] { + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn test_arg1_arg2() { + let scene = TestScenario::new(util_name!()); + + let expected = scene + .cmd_keepenv(util_name!()) + .env("LANGUAGE", "C") + .arg("am") + .arg("i") + .succeeds(); + + scene + .ucmd() + .arg("am") + .arg("i") + .succeeds() + .stdout_is(expected.stdout_str()); +} + +#[test] +fn test_too_many_args() { + let expected = + "error: The value 'u' was provided to '...', but it wasn't expecting any more values"; + + new_ucmd!() + .arg("am") + .arg("i") + .arg("u") + .fails() + .stderr_contains(expected); +} + +#[cfg(target_os = "linux")] +#[test] +fn test_users() { + for opt in vec!["-u", "--users"] { + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn test_lookup() { + for opt in vec!["--lookup"] { + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } @@ -61,15 +175,60 @@ fn test_m() { #[test] fn test_dead() { for opt in vec!["-d", "--dead"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } +#[cfg(target_os = "linux")] +#[test] +fn test_all_separately() { + // -a, --all same as -b -d --login -p -r -t -T -u + let scene = TestScenario::new(util_name!()); + + let expected = scene + .cmd_keepenv(util_name!()) + .env("LANGUAGE", "C") + .arg("-b") + .arg("-d") + .arg("--login") + .arg("-p") + .arg("-r") + .arg("-t") + .arg("-T") + .arg("-u") + .succeeds(); + + scene + .ucmd() + .arg("-b") + .arg("-d") + .arg("--login") + .arg("-p") + .arg("-r") + .arg("-t") + .arg("-T") + .arg("-u") + .succeeds() + .stdout_is(expected.stdout_str()); + + scene + .ucmd() + .arg("--all") + .succeeds() + .stdout_is(expected.stdout_str()); +} + #[cfg(target_os = "linux")] #[test] fn test_all() { for opt in vec!["-a", "--all"] { - new_ucmd!().arg(opt).run().stdout_is(expected_result(opt)); + new_ucmd!() + .arg(opt) + .succeeds() + .stdout_is(expected_result(opt)); } } @@ -79,6 +238,6 @@ fn expected_result(arg: &str) -> String { .cmd_keepenv(util_name!()) .env("LANGUAGE", "C") .args(&[arg]) - .run() + .succeeds() .stdout_move_str() } diff --git a/tests/fixtures/base64/input-simple.txt b/tests/fixtures/base64/input-simple.txt new file mode 100644 index 000000000..8ab686eaf --- /dev/null +++ b/tests/fixtures/base64/input-simple.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/tests/fixtures/sort/ext_sort.expected b/tests/fixtures/sort/ext_sort.expected new file mode 100644 index 000000000..7599e0c96 --- /dev/null +++ b/tests/fixtures/sort/ext_sort.expected @@ -0,0 +1,20000 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 +1688 +1689 +1690 +1691 +1692 +1693 +1694 +1695 +1696 +1697 +1698 +1699 +1700 +1701 +1702 +1703 +1704 +1705 +1706 +1707 +1708 +1709 +1710 +1711 +1712 +1713 +1714 +1715 +1716 +1717 +1718 +1719 +1720 +1721 +1722 +1723 +1724 +1725 +1726 +1727 +1728 +1729 +1730 +1731 +1732 +1733 +1734 +1735 +1736 +1737 +1738 +1739 +1740 +1741 +1742 +1743 +1744 +1745 +1746 +1747 +1748 +1749 +1750 +1751 +1752 +1753 +1754 +1755 +1756 +1757 +1758 +1759 +1760 +1761 +1762 +1763 +1764 +1765 +1766 +1767 +1768 +1769 +1770 +1771 +1772 +1773 +1774 +1775 +1776 +1777 +1778 +1779 +1780 +1781 +1782 +1783 +1784 +1785 +1786 +1787 +1788 +1789 +1790 +1791 +1792 +1793 +1794 +1795 +1796 +1797 +1798 +1799 +1800 +1801 +1802 +1803 +1804 +1805 +1806 +1807 +1808 +1809 +1810 +1811 +1812 +1813 +1814 +1815 +1816 +1817 +1818 +1819 +1820 +1821 +1822 +1823 +1824 +1825 +1826 +1827 +1828 +1829 +1830 +1831 +1832 +1833 +1834 +1835 +1836 +1837 +1838 +1839 +1840 +1841 +1842 +1843 +1844 +1845 +1846 +1847 +1848 +1849 +1850 +1851 +1852 +1853 +1854 +1855 +1856 +1857 +1858 +1859 +1860 +1861 +1862 +1863 +1864 +1865 +1866 +1867 +1868 +1869 +1870 +1871 +1872 +1873 +1874 +1875 +1876 +1877 +1878 +1879 +1880 +1881 +1882 +1883 +1884 +1885 +1886 +1887 +1888 +1889 +1890 +1891 +1892 +1893 +1894 +1895 +1896 +1897 +1898 +1899 +1900 +1901 +1902 +1903 +1904 +1905 +1906 +1907 +1908 +1909 +1910 +1911 +1912 +1913 +1914 +1915 +1916 +1917 +1918 +1919 +1920 +1921 +1922 +1923 +1924 +1925 +1926 +1927 +1928 +1929 +1930 +1931 +1932 +1933 +1934 +1935 +1936 +1937 +1938 +1939 +1940 +1941 +1942 +1943 +1944 +1945 +1946 +1947 +1948 +1949 +1950 +1951 +1952 +1953 +1954 +1955 +1956 +1957 +1958 +1959 +1960 +1961 +1962 +1963 +1964 +1965 +1966 +1967 +1968 +1969 +1970 +1971 +1972 +1973 +1974 +1975 +1976 +1977 +1978 +1979 +1980 +1981 +1982 +1983 +1984 +1985 +1986 +1987 +1988 +1989 +1990 +1991 +1992 +1993 +1994 +1995 +1996 +1997 +1998 +1999 +2000 +2001 +2002 +2003 +2004 +2005 +2006 +2007 +2008 +2009 +2010 +2011 +2012 +2013 +2014 +2015 +2016 +2017 +2018 +2019 +2020 +2021 +2022 +2023 +2024 +2025 +2026 +2027 +2028 +2029 +2030 +2031 +2032 +2033 +2034 +2035 +2036 +2037 +2038 +2039 +2040 +2041 +2042 +2043 +2044 +2045 +2046 +2047 +2048 +2049 +2050 +2051 +2052 +2053 +2054 +2055 +2056 +2057 +2058 +2059 +2060 +2061 +2062 +2063 +2064 +2065 +2066 +2067 +2068 +2069 +2070 +2071 +2072 +2073 +2074 +2075 +2076 +2077 +2078 +2079 +2080 +2081 +2082 +2083 +2084 +2085 +2086 +2087 +2088 +2089 +2090 +2091 +2092 +2093 +2094 +2095 +2096 +2097 +2098 +2099 +2100 +2101 +2102 +2103 +2104 +2105 +2106 +2107 +2108 +2109 +2110 +2111 +2112 +2113 +2114 +2115 +2116 +2117 +2118 +2119 +2120 +2121 +2122 +2123 +2124 +2125 +2126 +2127 +2128 +2129 +2130 +2131 +2132 +2133 +2134 +2135 +2136 +2137 +2138 +2139 +2140 +2141 +2142 +2143 +2144 +2145 +2146 +2147 +2148 +2149 +2150 +2151 +2152 +2153 +2154 +2155 +2156 +2157 +2158 +2159 +2160 +2161 +2162 +2163 +2164 +2165 +2166 +2167 +2168 +2169 +2170 +2171 +2172 +2173 +2174 +2175 +2176 +2177 +2178 +2179 +2180 +2181 +2182 +2183 +2184 +2185 +2186 +2187 +2188 +2189 +2190 +2191 +2192 +2193 +2194 +2195 +2196 +2197 +2198 +2199 +2200 +2201 +2202 +2203 +2204 +2205 +2206 +2207 +2208 +2209 +2210 +2211 +2212 +2213 +2214 +2215 +2216 +2217 +2218 +2219 +2220 +2221 +2222 +2223 +2224 +2225 +2226 +2227 +2228 +2229 +2230 +2231 +2232 +2233 +2234 +2235 +2236 +2237 +2238 +2239 +2240 +2241 +2242 +2243 +2244 +2245 +2246 +2247 +2248 +2249 +2250 +2251 +2252 +2253 +2254 +2255 +2256 +2257 +2258 +2259 +2260 +2261 +2262 +2263 +2264 +2265 +2266 +2267 +2268 +2269 +2270 +2271 +2272 +2273 +2274 +2275 +2276 +2277 +2278 +2279 +2280 +2281 +2282 +2283 +2284 +2285 +2286 +2287 +2288 +2289 +2290 +2291 +2292 +2293 +2294 +2295 +2296 +2297 +2298 +2299 +2300 +2301 +2302 +2303 +2304 +2305 +2306 +2307 +2308 +2309 +2310 +2311 +2312 +2313 +2314 +2315 +2316 +2317 +2318 +2319 +2320 +2321 +2322 +2323 +2324 +2325 +2326 +2327 +2328 +2329 +2330 +2331 +2332 +2333 +2334 +2335 +2336 +2337 +2338 +2339 +2340 +2341 +2342 +2343 +2344 +2345 +2346 +2347 +2348 +2349 +2350 +2351 +2352 +2353 +2354 +2355 +2356 +2357 +2358 +2359 +2360 +2361 +2362 +2363 +2364 +2365 +2366 +2367 +2368 +2369 +2370 +2371 +2372 +2373 +2374 +2375 +2376 +2377 +2378 +2379 +2380 +2381 +2382 +2383 +2384 +2385 +2386 +2387 +2388 +2389 +2390 +2391 +2392 +2393 +2394 +2395 +2396 +2397 +2398 +2399 +2400 +2401 +2402 +2403 +2404 +2405 +2406 +2407 +2408 +2409 +2410 +2411 +2412 +2413 +2414 +2415 +2416 +2417 +2418 +2419 +2420 +2421 +2422 +2423 +2424 +2425 +2426 +2427 +2428 +2429 +2430 +2431 +2432 +2433 +2434 +2435 +2436 +2437 +2438 +2439 +2440 +2441 +2442 +2443 +2444 +2445 +2446 +2447 +2448 +2449 +2450 +2451 +2452 +2453 +2454 +2455 +2456 +2457 +2458 +2459 +2460 +2461 +2462 +2463 +2464 +2465 +2466 +2467 +2468 +2469 +2470 +2471 +2472 +2473 +2474 +2475 +2476 +2477 +2478 +2479 +2480 +2481 +2482 +2483 +2484 +2485 +2486 +2487 +2488 +2489 +2490 +2491 +2492 +2493 +2494 +2495 +2496 +2497 +2498 +2499 +2500 +2501 +2502 +2503 +2504 +2505 +2506 +2507 +2508 +2509 +2510 +2511 +2512 +2513 +2514 +2515 +2516 +2517 +2518 +2519 +2520 +2521 +2522 +2523 +2524 +2525 +2526 +2527 +2528 +2529 +2530 +2531 +2532 +2533 +2534 +2535 +2536 +2537 +2538 +2539 +2540 +2541 +2542 +2543 +2544 +2545 +2546 +2547 +2548 +2549 +2550 +2551 +2552 +2553 +2554 +2555 +2556 +2557 +2558 +2559 +2560 +2561 +2562 +2563 +2564 +2565 +2566 +2567 +2568 +2569 +2570 +2571 +2572 +2573 +2574 +2575 +2576 +2577 +2578 +2579 +2580 +2581 +2582 +2583 +2584 +2585 +2586 +2587 +2588 +2589 +2590 +2591 +2592 +2593 +2594 +2595 +2596 +2597 +2598 +2599 +2600 +2601 +2602 +2603 +2604 +2605 +2606 +2607 +2608 +2609 +2610 +2611 +2612 +2613 +2614 +2615 +2616 +2617 +2618 +2619 +2620 +2621 +2622 +2623 +2624 +2625 +2626 +2627 +2628 +2629 +2630 +2631 +2632 +2633 +2634 +2635 +2636 +2637 +2638 +2639 +2640 +2641 +2642 +2643 +2644 +2645 +2646 +2647 +2648 +2649 +2650 +2651 +2652 +2653 +2654 +2655 +2656 +2657 +2658 +2659 +2660 +2661 +2662 +2663 +2664 +2665 +2666 +2667 +2668 +2669 +2670 +2671 +2672 +2673 +2674 +2675 +2676 +2677 +2678 +2679 +2680 +2681 +2682 +2683 +2684 +2685 +2686 +2687 +2688 +2689 +2690 +2691 +2692 +2693 +2694 +2695 +2696 +2697 +2698 +2699 +2700 +2701 +2702 +2703 +2704 +2705 +2706 +2707 +2708 +2709 +2710 +2711 +2712 +2713 +2714 +2715 +2716 +2717 +2718 +2719 +2720 +2721 +2722 +2723 +2724 +2725 +2726 +2727 +2728 +2729 +2730 +2731 +2732 +2733 +2734 +2735 +2736 +2737 +2738 +2739 +2740 +2741 +2742 +2743 +2744 +2745 +2746 +2747 +2748 +2749 +2750 +2751 +2752 +2753 +2754 +2755 +2756 +2757 +2758 +2759 +2760 +2761 +2762 +2763 +2764 +2765 +2766 +2767 +2768 +2769 +2770 +2771 +2772 +2773 +2774 +2775 +2776 +2777 +2778 +2779 +2780 +2781 +2782 +2783 +2784 +2785 +2786 +2787 +2788 +2789 +2790 +2791 +2792 +2793 +2794 +2795 +2796 +2797 +2798 +2799 +2800 +2801 +2802 +2803 +2804 +2805 +2806 +2807 +2808 +2809 +2810 +2811 +2812 +2813 +2814 +2815 +2816 +2817 +2818 +2819 +2820 +2821 +2822 +2823 +2824 +2825 +2826 +2827 +2828 +2829 +2830 +2831 +2832 +2833 +2834 +2835 +2836 +2837 +2838 +2839 +2840 +2841 +2842 +2843 +2844 +2845 +2846 +2847 +2848 +2849 +2850 +2851 +2852 +2853 +2854 +2855 +2856 +2857 +2858 +2859 +2860 +2861 +2862 +2863 +2864 +2865 +2866 +2867 +2868 +2869 +2870 +2871 +2872 +2873 +2874 +2875 +2876 +2877 +2878 +2879 +2880 +2881 +2882 +2883 +2884 +2885 +2886 +2887 +2888 +2889 +2890 +2891 +2892 +2893 +2894 +2895 +2896 +2897 +2898 +2899 +2900 +2901 +2902 +2903 +2904 +2905 +2906 +2907 +2908 +2909 +2910 +2911 +2912 +2913 +2914 +2915 +2916 +2917 +2918 +2919 +2920 +2921 +2922 +2923 +2924 +2925 +2926 +2927 +2928 +2929 +2930 +2931 +2932 +2933 +2934 +2935 +2936 +2937 +2938 +2939 +2940 +2941 +2942 +2943 +2944 +2945 +2946 +2947 +2948 +2949 +2950 +2951 +2952 +2953 +2954 +2955 +2956 +2957 +2958 +2959 +2960 +2961 +2962 +2963 +2964 +2965 +2966 +2967 +2968 +2969 +2970 +2971 +2972 +2973 +2974 +2975 +2976 +2977 +2978 +2979 +2980 +2981 +2982 +2983 +2984 +2985 +2986 +2987 +2988 +2989 +2990 +2991 +2992 +2993 +2994 +2995 +2996 +2997 +2998 +2999 +3000 +3001 +3002 +3003 +3004 +3005 +3006 +3007 +3008 +3009 +3010 +3011 +3012 +3013 +3014 +3015 +3016 +3017 +3018 +3019 +3020 +3021 +3022 +3023 +3024 +3025 +3026 +3027 +3028 +3029 +3030 +3031 +3032 +3033 +3034 +3035 +3036 +3037 +3038 +3039 +3040 +3041 +3042 +3043 +3044 +3045 +3046 +3047 +3048 +3049 +3050 +3051 +3052 +3053 +3054 +3055 +3056 +3057 +3058 +3059 +3060 +3061 +3062 +3063 +3064 +3065 +3066 +3067 +3068 +3069 +3070 +3071 +3072 +3073 +3074 +3075 +3076 +3077 +3078 +3079 +3080 +3081 +3082 +3083 +3084 +3085 +3086 +3087 +3088 +3089 +3090 +3091 +3092 +3093 +3094 +3095 +3096 +3097 +3098 +3099 +3100 +3101 +3102 +3103 +3104 +3105 +3106 +3107 +3108 +3109 +3110 +3111 +3112 +3113 +3114 +3115 +3116 +3117 +3118 +3119 +3120 +3121 +3122 +3123 +3124 +3125 +3126 +3127 +3128 +3129 +3130 +3131 +3132 +3133 +3134 +3135 +3136 +3137 +3138 +3139 +3140 +3141 +3142 +3143 +3144 +3145 +3146 +3147 +3148 +3149 +3150 +3151 +3152 +3153 +3154 +3155 +3156 +3157 +3158 +3159 +3160 +3161 +3162 +3163 +3164 +3165 +3166 +3167 +3168 +3169 +3170 +3171 +3172 +3173 +3174 +3175 +3176 +3177 +3178 +3179 +3180 +3181 +3182 +3183 +3184 +3185 +3186 +3187 +3188 +3189 +3190 +3191 +3192 +3193 +3194 +3195 +3196 +3197 +3198 +3199 +3200 +3201 +3202 +3203 +3204 +3205 +3206 +3207 +3208 +3209 +3210 +3211 +3212 +3213 +3214 +3215 +3216 +3217 +3218 +3219 +3220 +3221 +3222 +3223 +3224 +3225 +3226 +3227 +3228 +3229 +3230 +3231 +3232 +3233 +3234 +3235 +3236 +3237 +3238 +3239 +3240 +3241 +3242 +3243 +3244 +3245 +3246 +3247 +3248 +3249 +3250 +3251 +3252 +3253 +3254 +3255 +3256 +3257 +3258 +3259 +3260 +3261 +3262 +3263 +3264 +3265 +3266 +3267 +3268 +3269 +3270 +3271 +3272 +3273 +3274 +3275 +3276 +3277 +3278 +3279 +3280 +3281 +3282 +3283 +3284 +3285 +3286 +3287 +3288 +3289 +3290 +3291 +3292 +3293 +3294 +3295 +3296 +3297 +3298 +3299 +3300 +3301 +3302 +3303 +3304 +3305 +3306 +3307 +3308 +3309 +3310 +3311 +3312 +3313 +3314 +3315 +3316 +3317 +3318 +3319 +3320 +3321 +3322 +3323 +3324 +3325 +3326 +3327 +3328 +3329 +3330 +3331 +3332 +3333 +3334 +3335 +3336 +3337 +3338 +3339 +3340 +3341 +3342 +3343 +3344 +3345 +3346 +3347 +3348 +3349 +3350 +3351 +3352 +3353 +3354 +3355 +3356 +3357 +3358 +3359 +3360 +3361 +3362 +3363 +3364 +3365 +3366 +3367 +3368 +3369 +3370 +3371 +3372 +3373 +3374 +3375 +3376 +3377 +3378 +3379 +3380 +3381 +3382 +3383 +3384 +3385 +3386 +3387 +3388 +3389 +3390 +3391 +3392 +3393 +3394 +3395 +3396 +3397 +3398 +3399 +3400 +3401 +3402 +3403 +3404 +3405 +3406 +3407 +3408 +3409 +3410 +3411 +3412 +3413 +3414 +3415 +3416 +3417 +3418 +3419 +3420 +3421 +3422 +3423 +3424 +3425 +3426 +3427 +3428 +3429 +3430 +3431 +3432 +3433 +3434 +3435 +3436 +3437 +3438 +3439 +3440 +3441 +3442 +3443 +3444 +3445 +3446 +3447 +3448 +3449 +3450 +3451 +3452 +3453 +3454 +3455 +3456 +3457 +3458 +3459 +3460 +3461 +3462 +3463 +3464 +3465 +3466 +3467 +3468 +3469 +3470 +3471 +3472 +3473 +3474 +3475 +3476 +3477 +3478 +3479 +3480 +3481 +3482 +3483 +3484 +3485 +3486 +3487 +3488 +3489 +3490 +3491 +3492 +3493 +3494 +3495 +3496 +3497 +3498 +3499 +3500 +3501 +3502 +3503 +3504 +3505 +3506 +3507 +3508 +3509 +3510 +3511 +3512 +3513 +3514 +3515 +3516 +3517 +3518 +3519 +3520 +3521 +3522 +3523 +3524 +3525 +3526 +3527 +3528 +3529 +3530 +3531 +3532 +3533 +3534 +3535 +3536 +3537 +3538 +3539 +3540 +3541 +3542 +3543 +3544 +3545 +3546 +3547 +3548 +3549 +3550 +3551 +3552 +3553 +3554 +3555 +3556 +3557 +3558 +3559 +3560 +3561 +3562 +3563 +3564 +3565 +3566 +3567 +3568 +3569 +3570 +3571 +3572 +3573 +3574 +3575 +3576 +3577 +3578 +3579 +3580 +3581 +3582 +3583 +3584 +3585 +3586 +3587 +3588 +3589 +3590 +3591 +3592 +3593 +3594 +3595 +3596 +3597 +3598 +3599 +3600 +3601 +3602 +3603 +3604 +3605 +3606 +3607 +3608 +3609 +3610 +3611 +3612 +3613 +3614 +3615 +3616 +3617 +3618 +3619 +3620 +3621 +3622 +3623 +3624 +3625 +3626 +3627 +3628 +3629 +3630 +3631 +3632 +3633 +3634 +3635 +3636 +3637 +3638 +3639 +3640 +3641 +3642 +3643 +3644 +3645 +3646 +3647 +3648 +3649 +3650 +3651 +3652 +3653 +3654 +3655 +3656 +3657 +3658 +3659 +3660 +3661 +3662 +3663 +3664 +3665 +3666 +3667 +3668 +3669 +3670 +3671 +3672 +3673 +3674 +3675 +3676 +3677 +3678 +3679 +3680 +3681 +3682 +3683 +3684 +3685 +3686 +3687 +3688 +3689 +3690 +3691 +3692 +3693 +3694 +3695 +3696 +3697 +3698 +3699 +3700 +3701 +3702 +3703 +3704 +3705 +3706 +3707 +3708 +3709 +3710 +3711 +3712 +3713 +3714 +3715 +3716 +3717 +3718 +3719 +3720 +3721 +3722 +3723 +3724 +3725 +3726 +3727 +3728 +3729 +3730 +3731 +3732 +3733 +3734 +3735 +3736 +3737 +3738 +3739 +3740 +3741 +3742 +3743 +3744 +3745 +3746 +3747 +3748 +3749 +3750 +3751 +3752 +3753 +3754 +3755 +3756 +3757 +3758 +3759 +3760 +3761 +3762 +3763 +3764 +3765 +3766 +3767 +3768 +3769 +3770 +3771 +3772 +3773 +3774 +3775 +3776 +3777 +3778 +3779 +3780 +3781 +3782 +3783 +3784 +3785 +3786 +3787 +3788 +3789 +3790 +3791 +3792 +3793 +3794 +3795 +3796 +3797 +3798 +3799 +3800 +3801 +3802 +3803 +3804 +3805 +3806 +3807 +3808 +3809 +3810 +3811 +3812 +3813 +3814 +3815 +3816 +3817 +3818 +3819 +3820 +3821 +3822 +3823 +3824 +3825 +3826 +3827 +3828 +3829 +3830 +3831 +3832 +3833 +3834 +3835 +3836 +3837 +3838 +3839 +3840 +3841 +3842 +3843 +3844 +3845 +3846 +3847 +3848 +3849 +3850 +3851 +3852 +3853 +3854 +3855 +3856 +3857 +3858 +3859 +3860 +3861 +3862 +3863 +3864 +3865 +3866 +3867 +3868 +3869 +3870 +3871 +3872 +3873 +3874 +3875 +3876 +3877 +3878 +3879 +3880 +3881 +3882 +3883 +3884 +3885 +3886 +3887 +3888 +3889 +3890 +3891 +3892 +3893 +3894 +3895 +3896 +3897 +3898 +3899 +3900 +3901 +3902 +3903 +3904 +3905 +3906 +3907 +3908 +3909 +3910 +3911 +3912 +3913 +3914 +3915 +3916 +3917 +3918 +3919 +3920 +3921 +3922 +3923 +3924 +3925 +3926 +3927 +3928 +3929 +3930 +3931 +3932 +3933 +3934 +3935 +3936 +3937 +3938 +3939 +3940 +3941 +3942 +3943 +3944 +3945 +3946 +3947 +3948 +3949 +3950 +3951 +3952 +3953 +3954 +3955 +3956 +3957 +3958 +3959 +3960 +3961 +3962 +3963 +3964 +3965 +3966 +3967 +3968 +3969 +3970 +3971 +3972 +3973 +3974 +3975 +3976 +3977 +3978 +3979 +3980 +3981 +3982 +3983 +3984 +3985 +3986 +3987 +3988 +3989 +3990 +3991 +3992 +3993 +3994 +3995 +3996 +3997 +3998 +3999 +4000 +4001 +4002 +4003 +4004 +4005 +4006 +4007 +4008 +4009 +4010 +4011 +4012 +4013 +4014 +4015 +4016 +4017 +4018 +4019 +4020 +4021 +4022 +4023 +4024 +4025 +4026 +4027 +4028 +4029 +4030 +4031 +4032 +4033 +4034 +4035 +4036 +4037 +4038 +4039 +4040 +4041 +4042 +4043 +4044 +4045 +4046 +4047 +4048 +4049 +4050 +4051 +4052 +4053 +4054 +4055 +4056 +4057 +4058 +4059 +4060 +4061 +4062 +4063 +4064 +4065 +4066 +4067 +4068 +4069 +4070 +4071 +4072 +4073 +4074 +4075 +4076 +4077 +4078 +4079 +4080 +4081 +4082 +4083 +4084 +4085 +4086 +4087 +4088 +4089 +4090 +4091 +4092 +4093 +4094 +4095 +4096 +4097 +4098 +4099 +4100 +4101 +4102 +4103 +4104 +4105 +4106 +4107 +4108 +4109 +4110 +4111 +4112 +4113 +4114 +4115 +4116 +4117 +4118 +4119 +4120 +4121 +4122 +4123 +4124 +4125 +4126 +4127 +4128 +4129 +4130 +4131 +4132 +4133 +4134 +4135 +4136 +4137 +4138 +4139 +4140 +4141 +4142 +4143 +4144 +4145 +4146 +4147 +4148 +4149 +4150 +4151 +4152 +4153 +4154 +4155 +4156 +4157 +4158 +4159 +4160 +4161 +4162 +4163 +4164 +4165 +4166 +4167 +4168 +4169 +4170 +4171 +4172 +4173 +4174 +4175 +4176 +4177 +4178 +4179 +4180 +4181 +4182 +4183 +4184 +4185 +4186 +4187 +4188 +4189 +4190 +4191 +4192 +4193 +4194 +4195 +4196 +4197 +4198 +4199 +4200 +4201 +4202 +4203 +4204 +4205 +4206 +4207 +4208 +4209 +4210 +4211 +4212 +4213 +4214 +4215 +4216 +4217 +4218 +4219 +4220 +4221 +4222 +4223 +4224 +4225 +4226 +4227 +4228 +4229 +4230 +4231 +4232 +4233 +4234 +4235 +4236 +4237 +4238 +4239 +4240 +4241 +4242 +4243 +4244 +4245 +4246 +4247 +4248 +4249 +4250 +4251 +4252 +4253 +4254 +4255 +4256 +4257 +4258 +4259 +4260 +4261 +4262 +4263 +4264 +4265 +4266 +4267 +4268 +4269 +4270 +4271 +4272 +4273 +4274 +4275 +4276 +4277 +4278 +4279 +4280 +4281 +4282 +4283 +4284 +4285 +4286 +4287 +4288 +4289 +4290 +4291 +4292 +4293 +4294 +4295 +4296 +4297 +4298 +4299 +4300 +4301 +4302 +4303 +4304 +4305 +4306 +4307 +4308 +4309 +4310 +4311 +4312 +4313 +4314 +4315 +4316 +4317 +4318 +4319 +4320 +4321 +4322 +4323 +4324 +4325 +4326 +4327 +4328 +4329 +4330 +4331 +4332 +4333 +4334 +4335 +4336 +4337 +4338 +4339 +4340 +4341 +4342 +4343 +4344 +4345 +4346 +4347 +4348 +4349 +4350 +4351 +4352 +4353 +4354 +4355 +4356 +4357 +4358 +4359 +4360 +4361 +4362 +4363 +4364 +4365 +4366 +4367 +4368 +4369 +4370 +4371 +4372 +4373 +4374 +4375 +4376 +4377 +4378 +4379 +4380 +4381 +4382 +4383 +4384 +4385 +4386 +4387 +4388 +4389 +4390 +4391 +4392 +4393 +4394 +4395 +4396 +4397 +4398 +4399 +4400 +4401 +4402 +4403 +4404 +4405 +4406 +4407 +4408 +4409 +4410 +4411 +4412 +4413 +4414 +4415 +4416 +4417 +4418 +4419 +4420 +4421 +4422 +4423 +4424 +4425 +4426 +4427 +4428 +4429 +4430 +4431 +4432 +4433 +4434 +4435 +4436 +4437 +4438 +4439 +4440 +4441 +4442 +4443 +4444 +4445 +4446 +4447 +4448 +4449 +4450 +4451 +4452 +4453 +4454 +4455 +4456 +4457 +4458 +4459 +4460 +4461 +4462 +4463 +4464 +4465 +4466 +4467 +4468 +4469 +4470 +4471 +4472 +4473 +4474 +4475 +4476 +4477 +4478 +4479 +4480 +4481 +4482 +4483 +4484 +4485 +4486 +4487 +4488 +4489 +4490 +4491 +4492 +4493 +4494 +4495 +4496 +4497 +4498 +4499 +4500 +4501 +4502 +4503 +4504 +4505 +4506 +4507 +4508 +4509 +4510 +4511 +4512 +4513 +4514 +4515 +4516 +4517 +4518 +4519 +4520 +4521 +4522 +4523 +4524 +4525 +4526 +4527 +4528 +4529 +4530 +4531 +4532 +4533 +4534 +4535 +4536 +4537 +4538 +4539 +4540 +4541 +4542 +4543 +4544 +4545 +4546 +4547 +4548 +4549 +4550 +4551 +4552 +4553 +4554 +4555 +4556 +4557 +4558 +4559 +4560 +4561 +4562 +4563 +4564 +4565 +4566 +4567 +4568 +4569 +4570 +4571 +4572 +4573 +4574 +4575 +4576 +4577 +4578 +4579 +4580 +4581 +4582 +4583 +4584 +4585 +4586 +4587 +4588 +4589 +4590 +4591 +4592 +4593 +4594 +4595 +4596 +4597 +4598 +4599 +4600 +4601 +4602 +4603 +4604 +4605 +4606 +4607 +4608 +4609 +4610 +4611 +4612 +4613 +4614 +4615 +4616 +4617 +4618 +4619 +4620 +4621 +4622 +4623 +4624 +4625 +4626 +4627 +4628 +4629 +4630 +4631 +4632 +4633 +4634 +4635 +4636 +4637 +4638 +4639 +4640 +4641 +4642 +4643 +4644 +4645 +4646 +4647 +4648 +4649 +4650 +4651 +4652 +4653 +4654 +4655 +4656 +4657 +4658 +4659 +4660 +4661 +4662 +4663 +4664 +4665 +4666 +4667 +4668 +4669 +4670 +4671 +4672 +4673 +4674 +4675 +4676 +4677 +4678 +4679 +4680 +4681 +4682 +4683 +4684 +4685 +4686 +4687 +4688 +4689 +4690 +4691 +4692 +4693 +4694 +4695 +4696 +4697 +4698 +4699 +4700 +4701 +4702 +4703 +4704 +4705 +4706 +4707 +4708 +4709 +4710 +4711 +4712 +4713 +4714 +4715 +4716 +4717 +4718 +4719 +4720 +4721 +4722 +4723 +4724 +4725 +4726 +4727 +4728 +4729 +4730 +4731 +4732 +4733 +4734 +4735 +4736 +4737 +4738 +4739 +4740 +4741 +4742 +4743 +4744 +4745 +4746 +4747 +4748 +4749 +4750 +4751 +4752 +4753 +4754 +4755 +4756 +4757 +4758 +4759 +4760 +4761 +4762 +4763 +4764 +4765 +4766 +4767 +4768 +4769 +4770 +4771 +4772 +4773 +4774 +4775 +4776 +4777 +4778 +4779 +4780 +4781 +4782 +4783 +4784 +4785 +4786 +4787 +4788 +4789 +4790 +4791 +4792 +4793 +4794 +4795 +4796 +4797 +4798 +4799 +4800 +4801 +4802 +4803 +4804 +4805 +4806 +4807 +4808 +4809 +4810 +4811 +4812 +4813 +4814 +4815 +4816 +4817 +4818 +4819 +4820 +4821 +4822 +4823 +4824 +4825 +4826 +4827 +4828 +4829 +4830 +4831 +4832 +4833 +4834 +4835 +4836 +4837 +4838 +4839 +4840 +4841 +4842 +4843 +4844 +4845 +4846 +4847 +4848 +4849 +4850 +4851 +4852 +4853 +4854 +4855 +4856 +4857 +4858 +4859 +4860 +4861 +4862 +4863 +4864 +4865 +4866 +4867 +4868 +4869 +4870 +4871 +4872 +4873 +4874 +4875 +4876 +4877 +4878 +4879 +4880 +4881 +4882 +4883 +4884 +4885 +4886 +4887 +4888 +4889 +4890 +4891 +4892 +4893 +4894 +4895 +4896 +4897 +4898 +4899 +4900 +4901 +4902 +4903 +4904 +4905 +4906 +4907 +4908 +4909 +4910 +4911 +4912 +4913 +4914 +4915 +4916 +4917 +4918 +4919 +4920 +4921 +4922 +4923 +4924 +4925 +4926 +4927 +4928 +4929 +4930 +4931 +4932 +4933 +4934 +4935 +4936 +4937 +4938 +4939 +4940 +4941 +4942 +4943 +4944 +4945 +4946 +4947 +4948 +4949 +4950 +4951 +4952 +4953 +4954 +4955 +4956 +4957 +4958 +4959 +4960 +4961 +4962 +4963 +4964 +4965 +4966 +4967 +4968 +4969 +4970 +4971 +4972 +4973 +4974 +4975 +4976 +4977 +4978 +4979 +4980 +4981 +4982 +4983 +4984 +4985 +4986 +4987 +4988 +4989 +4990 +4991 +4992 +4993 +4994 +4995 +4996 +4997 +4998 +4999 +5000 +5001 +5002 +5003 +5004 +5005 +5006 +5007 +5008 +5009 +5010 +5011 +5012 +5013 +5014 +5015 +5016 +5017 +5018 +5019 +5020 +5021 +5022 +5023 +5024 +5025 +5026 +5027 +5028 +5029 +5030 +5031 +5032 +5033 +5034 +5035 +5036 +5037 +5038 +5039 +5040 +5041 +5042 +5043 +5044 +5045 +5046 +5047 +5048 +5049 +5050 +5051 +5052 +5053 +5054 +5055 +5056 +5057 +5058 +5059 +5060 +5061 +5062 +5063 +5064 +5065 +5066 +5067 +5068 +5069 +5070 +5071 +5072 +5073 +5074 +5075 +5076 +5077 +5078 +5079 +5080 +5081 +5082 +5083 +5084 +5085 +5086 +5087 +5088 +5089 +5090 +5091 +5092 +5093 +5094 +5095 +5096 +5097 +5098 +5099 +5100 +5101 +5102 +5103 +5104 +5105 +5106 +5107 +5108 +5109 +5110 +5111 +5112 +5113 +5114 +5115 +5116 +5117 +5118 +5119 +5120 +5121 +5122 +5123 +5124 +5125 +5126 +5127 +5128 +5129 +5130 +5131 +5132 +5133 +5134 +5135 +5136 +5137 +5138 +5139 +5140 +5141 +5142 +5143 +5144 +5145 +5146 +5147 +5148 +5149 +5150 +5151 +5152 +5153 +5154 +5155 +5156 +5157 +5158 +5159 +5160 +5161 +5162 +5163 +5164 +5165 +5166 +5167 +5168 +5169 +5170 +5171 +5172 +5173 +5174 +5175 +5176 +5177 +5178 +5179 +5180 +5181 +5182 +5183 +5184 +5185 +5186 +5187 +5188 +5189 +5190 +5191 +5192 +5193 +5194 +5195 +5196 +5197 +5198 +5199 +5200 +5201 +5202 +5203 +5204 +5205 +5206 +5207 +5208 +5209 +5210 +5211 +5212 +5213 +5214 +5215 +5216 +5217 +5218 +5219 +5220 +5221 +5222 +5223 +5224 +5225 +5226 +5227 +5228 +5229 +5230 +5231 +5232 +5233 +5234 +5235 +5236 +5237 +5238 +5239 +5240 +5241 +5242 +5243 +5244 +5245 +5246 +5247 +5248 +5249 +5250 +5251 +5252 +5253 +5254 +5255 +5256 +5257 +5258 +5259 +5260 +5261 +5262 +5263 +5264 +5265 +5266 +5267 +5268 +5269 +5270 +5271 +5272 +5273 +5274 +5275 +5276 +5277 +5278 +5279 +5280 +5281 +5282 +5283 +5284 +5285 +5286 +5287 +5288 +5289 +5290 +5291 +5292 +5293 +5294 +5295 +5296 +5297 +5298 +5299 +5300 +5301 +5302 +5303 +5304 +5305 +5306 +5307 +5308 +5309 +5310 +5311 +5312 +5313 +5314 +5315 +5316 +5317 +5318 +5319 +5320 +5321 +5322 +5323 +5324 +5325 +5326 +5327 +5328 +5329 +5330 +5331 +5332 +5333 +5334 +5335 +5336 +5337 +5338 +5339 +5340 +5341 +5342 +5343 +5344 +5345 +5346 +5347 +5348 +5349 +5350 +5351 +5352 +5353 +5354 +5355 +5356 +5357 +5358 +5359 +5360 +5361 +5362 +5363 +5364 +5365 +5366 +5367 +5368 +5369 +5370 +5371 +5372 +5373 +5374 +5375 +5376 +5377 +5378 +5379 +5380 +5381 +5382 +5383 +5384 +5385 +5386 +5387 +5388 +5389 +5390 +5391 +5392 +5393 +5394 +5395 +5396 +5397 +5398 +5399 +5400 +5401 +5402 +5403 +5404 +5405 +5406 +5407 +5408 +5409 +5410 +5411 +5412 +5413 +5414 +5415 +5416 +5417 +5418 +5419 +5420 +5421 +5422 +5423 +5424 +5425 +5426 +5427 +5428 +5429 +5430 +5431 +5432 +5433 +5434 +5435 +5436 +5437 +5438 +5439 +5440 +5441 +5442 +5443 +5444 +5445 +5446 +5447 +5448 +5449 +5450 +5451 +5452 +5453 +5454 +5455 +5456 +5457 +5458 +5459 +5460 +5461 +5462 +5463 +5464 +5465 +5466 +5467 +5468 +5469 +5470 +5471 +5472 +5473 +5474 +5475 +5476 +5477 +5478 +5479 +5480 +5481 +5482 +5483 +5484 +5485 +5486 +5487 +5488 +5489 +5490 +5491 +5492 +5493 +5494 +5495 +5496 +5497 +5498 +5499 +5500 +5501 +5502 +5503 +5504 +5505 +5506 +5507 +5508 +5509 +5510 +5511 +5512 +5513 +5514 +5515 +5516 +5517 +5518 +5519 +5520 +5521 +5522 +5523 +5524 +5525 +5526 +5527 +5528 +5529 +5530 +5531 +5532 +5533 +5534 +5535 +5536 +5537 +5538 +5539 +5540 +5541 +5542 +5543 +5544 +5545 +5546 +5547 +5548 +5549 +5550 +5551 +5552 +5553 +5554 +5555 +5556 +5557 +5558 +5559 +5560 +5561 +5562 +5563 +5564 +5565 +5566 +5567 +5568 +5569 +5570 +5571 +5572 +5573 +5574 +5575 +5576 +5577 +5578 +5579 +5580 +5581 +5582 +5583 +5584 +5585 +5586 +5587 +5588 +5589 +5590 +5591 +5592 +5593 +5594 +5595 +5596 +5597 +5598 +5599 +5600 +5601 +5602 +5603 +5604 +5605 +5606 +5607 +5608 +5609 +5610 +5611 +5612 +5613 +5614 +5615 +5616 +5617 +5618 +5619 +5620 +5621 +5622 +5623 +5624 +5625 +5626 +5627 +5628 +5629 +5630 +5631 +5632 +5633 +5634 +5635 +5636 +5637 +5638 +5639 +5640 +5641 +5642 +5643 +5644 +5645 +5646 +5647 +5648 +5649 +5650 +5651 +5652 +5653 +5654 +5655 +5656 +5657 +5658 +5659 +5660 +5661 +5662 +5663 +5664 +5665 +5666 +5667 +5668 +5669 +5670 +5671 +5672 +5673 +5674 +5675 +5676 +5677 +5678 +5679 +5680 +5681 +5682 +5683 +5684 +5685 +5686 +5687 +5688 +5689 +5690 +5691 +5692 +5693 +5694 +5695 +5696 +5697 +5698 +5699 +5700 +5701 +5702 +5703 +5704 +5705 +5706 +5707 +5708 +5709 +5710 +5711 +5712 +5713 +5714 +5715 +5716 +5717 +5718 +5719 +5720 +5721 +5722 +5723 +5724 +5725 +5726 +5727 +5728 +5729 +5730 +5731 +5732 +5733 +5734 +5735 +5736 +5737 +5738 +5739 +5740 +5741 +5742 +5743 +5744 +5745 +5746 +5747 +5748 +5749 +5750 +5751 +5752 +5753 +5754 +5755 +5756 +5757 +5758 +5759 +5760 +5761 +5762 +5763 +5764 +5765 +5766 +5767 +5768 +5769 +5770 +5771 +5772 +5773 +5774 +5775 +5776 +5777 +5778 +5779 +5780 +5781 +5782 +5783 +5784 +5785 +5786 +5787 +5788 +5789 +5790 +5791 +5792 +5793 +5794 +5795 +5796 +5797 +5798 +5799 +5800 +5801 +5802 +5803 +5804 +5805 +5806 +5807 +5808 +5809 +5810 +5811 +5812 +5813 +5814 +5815 +5816 +5817 +5818 +5819 +5820 +5821 +5822 +5823 +5824 +5825 +5826 +5827 +5828 +5829 +5830 +5831 +5832 +5833 +5834 +5835 +5836 +5837 +5838 +5839 +5840 +5841 +5842 +5843 +5844 +5845 +5846 +5847 +5848 +5849 +5850 +5851 +5852 +5853 +5854 +5855 +5856 +5857 +5858 +5859 +5860 +5861 +5862 +5863 +5864 +5865 +5866 +5867 +5868 +5869 +5870 +5871 +5872 +5873 +5874 +5875 +5876 +5877 +5878 +5879 +5880 +5881 +5882 +5883 +5884 +5885 +5886 +5887 +5888 +5889 +5890 +5891 +5892 +5893 +5894 +5895 +5896 +5897 +5898 +5899 +5900 +5901 +5902 +5903 +5904 +5905 +5906 +5907 +5908 +5909 +5910 +5911 +5912 +5913 +5914 +5915 +5916 +5917 +5918 +5919 +5920 +5921 +5922 +5923 +5924 +5925 +5926 +5927 +5928 +5929 +5930 +5931 +5932 +5933 +5934 +5935 +5936 +5937 +5938 +5939 +5940 +5941 +5942 +5943 +5944 +5945 +5946 +5947 +5948 +5949 +5950 +5951 +5952 +5953 +5954 +5955 +5956 +5957 +5958 +5959 +5960 +5961 +5962 +5963 +5964 +5965 +5966 +5967 +5968 +5969 +5970 +5971 +5972 +5973 +5974 +5975 +5976 +5977 +5978 +5979 +5980 +5981 +5982 +5983 +5984 +5985 +5986 +5987 +5988 +5989 +5990 +5991 +5992 +5993 +5994 +5995 +5996 +5997 +5998 +5999 +6000 +6001 +6002 +6003 +6004 +6005 +6006 +6007 +6008 +6009 +6010 +6011 +6012 +6013 +6014 +6015 +6016 +6017 +6018 +6019 +6020 +6021 +6022 +6023 +6024 +6025 +6026 +6027 +6028 +6029 +6030 +6031 +6032 +6033 +6034 +6035 +6036 +6037 +6038 +6039 +6040 +6041 +6042 +6043 +6044 +6045 +6046 +6047 +6048 +6049 +6050 +6051 +6052 +6053 +6054 +6055 +6056 +6057 +6058 +6059 +6060 +6061 +6062 +6063 +6064 +6065 +6066 +6067 +6068 +6069 +6070 +6071 +6072 +6073 +6074 +6075 +6076 +6077 +6078 +6079 +6080 +6081 +6082 +6083 +6084 +6085 +6086 +6087 +6088 +6089 +6090 +6091 +6092 +6093 +6094 +6095 +6096 +6097 +6098 +6099 +6100 +6101 +6102 +6103 +6104 +6105 +6106 +6107 +6108 +6109 +6110 +6111 +6112 +6113 +6114 +6115 +6116 +6117 +6118 +6119 +6120 +6121 +6122 +6123 +6124 +6125 +6126 +6127 +6128 +6129 +6130 +6131 +6132 +6133 +6134 +6135 +6136 +6137 +6138 +6139 +6140 +6141 +6142 +6143 +6144 +6145 +6146 +6147 +6148 +6149 +6150 +6151 +6152 +6153 +6154 +6155 +6156 +6157 +6158 +6159 +6160 +6161 +6162 +6163 +6164 +6165 +6166 +6167 +6168 +6169 +6170 +6171 +6172 +6173 +6174 +6175 +6176 +6177 +6178 +6179 +6180 +6181 +6182 +6183 +6184 +6185 +6186 +6187 +6188 +6189 +6190 +6191 +6192 +6193 +6194 +6195 +6196 +6197 +6198 +6199 +6200 +6201 +6202 +6203 +6204 +6205 +6206 +6207 +6208 +6209 +6210 +6211 +6212 +6213 +6214 +6215 +6216 +6217 +6218 +6219 +6220 +6221 +6222 +6223 +6224 +6225 +6226 +6227 +6228 +6229 +6230 +6231 +6232 +6233 +6234 +6235 +6236 +6237 +6238 +6239 +6240 +6241 +6242 +6243 +6244 +6245 +6246 +6247 +6248 +6249 +6250 +6251 +6252 +6253 +6254 +6255 +6256 +6257 +6258 +6259 +6260 +6261 +6262 +6263 +6264 +6265 +6266 +6267 +6268 +6269 +6270 +6271 +6272 +6273 +6274 +6275 +6276 +6277 +6278 +6279 +6280 +6281 +6282 +6283 +6284 +6285 +6286 +6287 +6288 +6289 +6290 +6291 +6292 +6293 +6294 +6295 +6296 +6297 +6298 +6299 +6300 +6301 +6302 +6303 +6304 +6305 +6306 +6307 +6308 +6309 +6310 +6311 +6312 +6313 +6314 +6315 +6316 +6317 +6318 +6319 +6320 +6321 +6322 +6323 +6324 +6325 +6326 +6327 +6328 +6329 +6330 +6331 +6332 +6333 +6334 +6335 +6336 +6337 +6338 +6339 +6340 +6341 +6342 +6343 +6344 +6345 +6346 +6347 +6348 +6349 +6350 +6351 +6352 +6353 +6354 +6355 +6356 +6357 +6358 +6359 +6360 +6361 +6362 +6363 +6364 +6365 +6366 +6367 +6368 +6369 +6370 +6371 +6372 +6373 +6374 +6375 +6376 +6377 +6378 +6379 +6380 +6381 +6382 +6383 +6384 +6385 +6386 +6387 +6388 +6389 +6390 +6391 +6392 +6393 +6394 +6395 +6396 +6397 +6398 +6399 +6400 +6401 +6402 +6403 +6404 +6405 +6406 +6407 +6408 +6409 +6410 +6411 +6412 +6413 +6414 +6415 +6416 +6417 +6418 +6419 +6420 +6421 +6422 +6423 +6424 +6425 +6426 +6427 +6428 +6429 +6430 +6431 +6432 +6433 +6434 +6435 +6436 +6437 +6438 +6439 +6440 +6441 +6442 +6443 +6444 +6445 +6446 +6447 +6448 +6449 +6450 +6451 +6452 +6453 +6454 +6455 +6456 +6457 +6458 +6459 +6460 +6461 +6462 +6463 +6464 +6465 +6466 +6467 +6468 +6469 +6470 +6471 +6472 +6473 +6474 +6475 +6476 +6477 +6478 +6479 +6480 +6481 +6482 +6483 +6484 +6485 +6486 +6487 +6488 +6489 +6490 +6491 +6492 +6493 +6494 +6495 +6496 +6497 +6498 +6499 +6500 +6501 +6502 +6503 +6504 +6505 +6506 +6507 +6508 +6509 +6510 +6511 +6512 +6513 +6514 +6515 +6516 +6517 +6518 +6519 +6520 +6521 +6522 +6523 +6524 +6525 +6526 +6527 +6528 +6529 +6530 +6531 +6532 +6533 +6534 +6535 +6536 +6537 +6538 +6539 +6540 +6541 +6542 +6543 +6544 +6545 +6546 +6547 +6548 +6549 +6550 +6551 +6552 +6553 +6554 +6555 +6556 +6557 +6558 +6559 +6560 +6561 +6562 +6563 +6564 +6565 +6566 +6567 +6568 +6569 +6570 +6571 +6572 +6573 +6574 +6575 +6576 +6577 +6578 +6579 +6580 +6581 +6582 +6583 +6584 +6585 +6586 +6587 +6588 +6589 +6590 +6591 +6592 +6593 +6594 +6595 +6596 +6597 +6598 +6599 +6600 +6601 +6602 +6603 +6604 +6605 +6606 +6607 +6608 +6609 +6610 +6611 +6612 +6613 +6614 +6615 +6616 +6617 +6618 +6619 +6620 +6621 +6622 +6623 +6624 +6625 +6626 +6627 +6628 +6629 +6630 +6631 +6632 +6633 +6634 +6635 +6636 +6637 +6638 +6639 +6640 +6641 +6642 +6643 +6644 +6645 +6646 +6647 +6648 +6649 +6650 +6651 +6652 +6653 +6654 +6655 +6656 +6657 +6658 +6659 +6660 +6661 +6662 +6663 +6664 +6665 +6666 +6667 +6668 +6669 +6670 +6671 +6672 +6673 +6674 +6675 +6676 +6677 +6678 +6679 +6680 +6681 +6682 +6683 +6684 +6685 +6686 +6687 +6688 +6689 +6690 +6691 +6692 +6693 +6694 +6695 +6696 +6697 +6698 +6699 +6700 +6701 +6702 +6703 +6704 +6705 +6706 +6707 +6708 +6709 +6710 +6711 +6712 +6713 +6714 +6715 +6716 +6717 +6718 +6719 +6720 +6721 +6722 +6723 +6724 +6725 +6726 +6727 +6728 +6729 +6730 +6731 +6732 +6733 +6734 +6735 +6736 +6737 +6738 +6739 +6740 +6741 +6742 +6743 +6744 +6745 +6746 +6747 +6748 +6749 +6750 +6751 +6752 +6753 +6754 +6755 +6756 +6757 +6758 +6759 +6760 +6761 +6762 +6763 +6764 +6765 +6766 +6767 +6768 +6769 +6770 +6771 +6772 +6773 +6774 +6775 +6776 +6777 +6778 +6779 +6780 +6781 +6782 +6783 +6784 +6785 +6786 +6787 +6788 +6789 +6790 +6791 +6792 +6793 +6794 +6795 +6796 +6797 +6798 +6799 +6800 +6801 +6802 +6803 +6804 +6805 +6806 +6807 +6808 +6809 +6810 +6811 +6812 +6813 +6814 +6815 +6816 +6817 +6818 +6819 +6820 +6821 +6822 +6823 +6824 +6825 +6826 +6827 +6828 +6829 +6830 +6831 +6832 +6833 +6834 +6835 +6836 +6837 +6838 +6839 +6840 +6841 +6842 +6843 +6844 +6845 +6846 +6847 +6848 +6849 +6850 +6851 +6852 +6853 +6854 +6855 +6856 +6857 +6858 +6859 +6860 +6861 +6862 +6863 +6864 +6865 +6866 +6867 +6868 +6869 +6870 +6871 +6872 +6873 +6874 +6875 +6876 +6877 +6878 +6879 +6880 +6881 +6882 +6883 +6884 +6885 +6886 +6887 +6888 +6889 +6890 +6891 +6892 +6893 +6894 +6895 +6896 +6897 +6898 +6899 +6900 +6901 +6902 +6903 +6904 +6905 +6906 +6907 +6908 +6909 +6910 +6911 +6912 +6913 +6914 +6915 +6916 +6917 +6918 +6919 +6920 +6921 +6922 +6923 +6924 +6925 +6926 +6927 +6928 +6929 +6930 +6931 +6932 +6933 +6934 +6935 +6936 +6937 +6938 +6939 +6940 +6941 +6942 +6943 +6944 +6945 +6946 +6947 +6948 +6949 +6950 +6951 +6952 +6953 +6954 +6955 +6956 +6957 +6958 +6959 +6960 +6961 +6962 +6963 +6964 +6965 +6966 +6967 +6968 +6969 +6970 +6971 +6972 +6973 +6974 +6975 +6976 +6977 +6978 +6979 +6980 +6981 +6982 +6983 +6984 +6985 +6986 +6987 +6988 +6989 +6990 +6991 +6992 +6993 +6994 +6995 +6996 +6997 +6998 +6999 +7000 +7001 +7002 +7003 +7004 +7005 +7006 +7007 +7008 +7009 +7010 +7011 +7012 +7013 +7014 +7015 +7016 +7017 +7018 +7019 +7020 +7021 +7022 +7023 +7024 +7025 +7026 +7027 +7028 +7029 +7030 +7031 +7032 +7033 +7034 +7035 +7036 +7037 +7038 +7039 +7040 +7041 +7042 +7043 +7044 +7045 +7046 +7047 +7048 +7049 +7050 +7051 +7052 +7053 +7054 +7055 +7056 +7057 +7058 +7059 +7060 +7061 +7062 +7063 +7064 +7065 +7066 +7067 +7068 +7069 +7070 +7071 +7072 +7073 +7074 +7075 +7076 +7077 +7078 +7079 +7080 +7081 +7082 +7083 +7084 +7085 +7086 +7087 +7088 +7089 +7090 +7091 +7092 +7093 +7094 +7095 +7096 +7097 +7098 +7099 +7100 +7101 +7102 +7103 +7104 +7105 +7106 +7107 +7108 +7109 +7110 +7111 +7112 +7113 +7114 +7115 +7116 +7117 +7118 +7119 +7120 +7121 +7122 +7123 +7124 +7125 +7126 +7127 +7128 +7129 +7130 +7131 +7132 +7133 +7134 +7135 +7136 +7137 +7138 +7139 +7140 +7141 +7142 +7143 +7144 +7145 +7146 +7147 +7148 +7149 +7150 +7151 +7152 +7153 +7154 +7155 +7156 +7157 +7158 +7159 +7160 +7161 +7162 +7163 +7164 +7165 +7166 +7167 +7168 +7169 +7170 +7171 +7172 +7173 +7174 +7175 +7176 +7177 +7178 +7179 +7180 +7181 +7182 +7183 +7184 +7185 +7186 +7187 +7188 +7189 +7190 +7191 +7192 +7193 +7194 +7195 +7196 +7197 +7198 +7199 +7200 +7201 +7202 +7203 +7204 +7205 +7206 +7207 +7208 +7209 +7210 +7211 +7212 +7213 +7214 +7215 +7216 +7217 +7218 +7219 +7220 +7221 +7222 +7223 +7224 +7225 +7226 +7227 +7228 +7229 +7230 +7231 +7232 +7233 +7234 +7235 +7236 +7237 +7238 +7239 +7240 +7241 +7242 +7243 +7244 +7245 +7246 +7247 +7248 +7249 +7250 +7251 +7252 +7253 +7254 +7255 +7256 +7257 +7258 +7259 +7260 +7261 +7262 +7263 +7264 +7265 +7266 +7267 +7268 +7269 +7270 +7271 +7272 +7273 +7274 +7275 +7276 +7277 +7278 +7279 +7280 +7281 +7282 +7283 +7284 +7285 +7286 +7287 +7288 +7289 +7290 +7291 +7292 +7293 +7294 +7295 +7296 +7297 +7298 +7299 +7300 +7301 +7302 +7303 +7304 +7305 +7306 +7307 +7308 +7309 +7310 +7311 +7312 +7313 +7314 +7315 +7316 +7317 +7318 +7319 +7320 +7321 +7322 +7323 +7324 +7325 +7326 +7327 +7328 +7329 +7330 +7331 +7332 +7333 +7334 +7335 +7336 +7337 +7338 +7339 +7340 +7341 +7342 +7343 +7344 +7345 +7346 +7347 +7348 +7349 +7350 +7351 +7352 +7353 +7354 +7355 +7356 +7357 +7358 +7359 +7360 +7361 +7362 +7363 +7364 +7365 +7366 +7367 +7368 +7369 +7370 +7371 +7372 +7373 +7374 +7375 +7376 +7377 +7378 +7379 +7380 +7381 +7382 +7383 +7384 +7385 +7386 +7387 +7388 +7389 +7390 +7391 +7392 +7393 +7394 +7395 +7396 +7397 +7398 +7399 +7400 +7401 +7402 +7403 +7404 +7405 +7406 +7407 +7408 +7409 +7410 +7411 +7412 +7413 +7414 +7415 +7416 +7417 +7418 +7419 +7420 +7421 +7422 +7423 +7424 +7425 +7426 +7427 +7428 +7429 +7430 +7431 +7432 +7433 +7434 +7435 +7436 +7437 +7438 +7439 +7440 +7441 +7442 +7443 +7444 +7445 +7446 +7447 +7448 +7449 +7450 +7451 +7452 +7453 +7454 +7455 +7456 +7457 +7458 +7459 +7460 +7461 +7462 +7463 +7464 +7465 +7466 +7467 +7468 +7469 +7470 +7471 +7472 +7473 +7474 +7475 +7476 +7477 +7478 +7479 +7480 +7481 +7482 +7483 +7484 +7485 +7486 +7487 +7488 +7489 +7490 +7491 +7492 +7493 +7494 +7495 +7496 +7497 +7498 +7499 +7500 +7501 +7502 +7503 +7504 +7505 +7506 +7507 +7508 +7509 +7510 +7511 +7512 +7513 +7514 +7515 +7516 +7517 +7518 +7519 +7520 +7521 +7522 +7523 +7524 +7525 +7526 +7527 +7528 +7529 +7530 +7531 +7532 +7533 +7534 +7535 +7536 +7537 +7538 +7539 +7540 +7541 +7542 +7543 +7544 +7545 +7546 +7547 +7548 +7549 +7550 +7551 +7552 +7553 +7554 +7555 +7556 +7557 +7558 +7559 +7560 +7561 +7562 +7563 +7564 +7565 +7566 +7567 +7568 +7569 +7570 +7571 +7572 +7573 +7574 +7575 +7576 +7577 +7578 +7579 +7580 +7581 +7582 +7583 +7584 +7585 +7586 +7587 +7588 +7589 +7590 +7591 +7592 +7593 +7594 +7595 +7596 +7597 +7598 +7599 +7600 +7601 +7602 +7603 +7604 +7605 +7606 +7607 +7608 +7609 +7610 +7611 +7612 +7613 +7614 +7615 +7616 +7617 +7618 +7619 +7620 +7621 +7622 +7623 +7624 +7625 +7626 +7627 +7628 +7629 +7630 +7631 +7632 +7633 +7634 +7635 +7636 +7637 +7638 +7639 +7640 +7641 +7642 +7643 +7644 +7645 +7646 +7647 +7648 +7649 +7650 +7651 +7652 +7653 +7654 +7655 +7656 +7657 +7658 +7659 +7660 +7661 +7662 +7663 +7664 +7665 +7666 +7667 +7668 +7669 +7670 +7671 +7672 +7673 +7674 +7675 +7676 +7677 +7678 +7679 +7680 +7681 +7682 +7683 +7684 +7685 +7686 +7687 +7688 +7689 +7690 +7691 +7692 +7693 +7694 +7695 +7696 +7697 +7698 +7699 +7700 +7701 +7702 +7703 +7704 +7705 +7706 +7707 +7708 +7709 +7710 +7711 +7712 +7713 +7714 +7715 +7716 +7717 +7718 +7719 +7720 +7721 +7722 +7723 +7724 +7725 +7726 +7727 +7728 +7729 +7730 +7731 +7732 +7733 +7734 +7735 +7736 +7737 +7738 +7739 +7740 +7741 +7742 +7743 +7744 +7745 +7746 +7747 +7748 +7749 +7750 +7751 +7752 +7753 +7754 +7755 +7756 +7757 +7758 +7759 +7760 +7761 +7762 +7763 +7764 +7765 +7766 +7767 +7768 +7769 +7770 +7771 +7772 +7773 +7774 +7775 +7776 +7777 +7778 +7779 +7780 +7781 +7782 +7783 +7784 +7785 +7786 +7787 +7788 +7789 +7790 +7791 +7792 +7793 +7794 +7795 +7796 +7797 +7798 +7799 +7800 +7801 +7802 +7803 +7804 +7805 +7806 +7807 +7808 +7809 +7810 +7811 +7812 +7813 +7814 +7815 +7816 +7817 +7818 +7819 +7820 +7821 +7822 +7823 +7824 +7825 +7826 +7827 +7828 +7829 +7830 +7831 +7832 +7833 +7834 +7835 +7836 +7837 +7838 +7839 +7840 +7841 +7842 +7843 +7844 +7845 +7846 +7847 +7848 +7849 +7850 +7851 +7852 +7853 +7854 +7855 +7856 +7857 +7858 +7859 +7860 +7861 +7862 +7863 +7864 +7865 +7866 +7867 +7868 +7869 +7870 +7871 +7872 +7873 +7874 +7875 +7876 +7877 +7878 +7879 +7880 +7881 +7882 +7883 +7884 +7885 +7886 +7887 +7888 +7889 +7890 +7891 +7892 +7893 +7894 +7895 +7896 +7897 +7898 +7899 +7900 +7901 +7902 +7903 +7904 +7905 +7906 +7907 +7908 +7909 +7910 +7911 +7912 +7913 +7914 +7915 +7916 +7917 +7918 +7919 +7920 +7921 +7922 +7923 +7924 +7925 +7926 +7927 +7928 +7929 +7930 +7931 +7932 +7933 +7934 +7935 +7936 +7937 +7938 +7939 +7940 +7941 +7942 +7943 +7944 +7945 +7946 +7947 +7948 +7949 +7950 +7951 +7952 +7953 +7954 +7955 +7956 +7957 +7958 +7959 +7960 +7961 +7962 +7963 +7964 +7965 +7966 +7967 +7968 +7969 +7970 +7971 +7972 +7973 +7974 +7975 +7976 +7977 +7978 +7979 +7980 +7981 +7982 +7983 +7984 +7985 +7986 +7987 +7988 +7989 +7990 +7991 +7992 +7993 +7994 +7995 +7996 +7997 +7998 +7999 +8000 +8001 +8002 +8003 +8004 +8005 +8006 +8007 +8008 +8009 +8010 +8011 +8012 +8013 +8014 +8015 +8016 +8017 +8018 +8019 +8020 +8021 +8022 +8023 +8024 +8025 +8026 +8027 +8028 +8029 +8030 +8031 +8032 +8033 +8034 +8035 +8036 +8037 +8038 +8039 +8040 +8041 +8042 +8043 +8044 +8045 +8046 +8047 +8048 +8049 +8050 +8051 +8052 +8053 +8054 +8055 +8056 +8057 +8058 +8059 +8060 +8061 +8062 +8063 +8064 +8065 +8066 +8067 +8068 +8069 +8070 +8071 +8072 +8073 +8074 +8075 +8076 +8077 +8078 +8079 +8080 +8081 +8082 +8083 +8084 +8085 +8086 +8087 +8088 +8089 +8090 +8091 +8092 +8093 +8094 +8095 +8096 +8097 +8098 +8099 +8100 +8101 +8102 +8103 +8104 +8105 +8106 +8107 +8108 +8109 +8110 +8111 +8112 +8113 +8114 +8115 +8116 +8117 +8118 +8119 +8120 +8121 +8122 +8123 +8124 +8125 +8126 +8127 +8128 +8129 +8130 +8131 +8132 +8133 +8134 +8135 +8136 +8137 +8138 +8139 +8140 +8141 +8142 +8143 +8144 +8145 +8146 +8147 +8148 +8149 +8150 +8151 +8152 +8153 +8154 +8155 +8156 +8157 +8158 +8159 +8160 +8161 +8162 +8163 +8164 +8165 +8166 +8167 +8168 +8169 +8170 +8171 +8172 +8173 +8174 +8175 +8176 +8177 +8178 +8179 +8180 +8181 +8182 +8183 +8184 +8185 +8186 +8187 +8188 +8189 +8190 +8191 +8192 +8193 +8194 +8195 +8196 +8197 +8198 +8199 +8200 +8201 +8202 +8203 +8204 +8205 +8206 +8207 +8208 +8209 +8210 +8211 +8212 +8213 +8214 +8215 +8216 +8217 +8218 +8219 +8220 +8221 +8222 +8223 +8224 +8225 +8226 +8227 +8228 +8229 +8230 +8231 +8232 +8233 +8234 +8235 +8236 +8237 +8238 +8239 +8240 +8241 +8242 +8243 +8244 +8245 +8246 +8247 +8248 +8249 +8250 +8251 +8252 +8253 +8254 +8255 +8256 +8257 +8258 +8259 +8260 +8261 +8262 +8263 +8264 +8265 +8266 +8267 +8268 +8269 +8270 +8271 +8272 +8273 +8274 +8275 +8276 +8277 +8278 +8279 +8280 +8281 +8282 +8283 +8284 +8285 +8286 +8287 +8288 +8289 +8290 +8291 +8292 +8293 +8294 +8295 +8296 +8297 +8298 +8299 +8300 +8301 +8302 +8303 +8304 +8305 +8306 +8307 +8308 +8309 +8310 +8311 +8312 +8313 +8314 +8315 +8316 +8317 +8318 +8319 +8320 +8321 +8322 +8323 +8324 +8325 +8326 +8327 +8328 +8329 +8330 +8331 +8332 +8333 +8334 +8335 +8336 +8337 +8338 +8339 +8340 +8341 +8342 +8343 +8344 +8345 +8346 +8347 +8348 +8349 +8350 +8351 +8352 +8353 +8354 +8355 +8356 +8357 +8358 +8359 +8360 +8361 +8362 +8363 +8364 +8365 +8366 +8367 +8368 +8369 +8370 +8371 +8372 +8373 +8374 +8375 +8376 +8377 +8378 +8379 +8380 +8381 +8382 +8383 +8384 +8385 +8386 +8387 +8388 +8389 +8390 +8391 +8392 +8393 +8394 +8395 +8396 +8397 +8398 +8399 +8400 +8401 +8402 +8403 +8404 +8405 +8406 +8407 +8408 +8409 +8410 +8411 +8412 +8413 +8414 +8415 +8416 +8417 +8418 +8419 +8420 +8421 +8422 +8423 +8424 +8425 +8426 +8427 +8428 +8429 +8430 +8431 +8432 +8433 +8434 +8435 +8436 +8437 +8438 +8439 +8440 +8441 +8442 +8443 +8444 +8445 +8446 +8447 +8448 +8449 +8450 +8451 +8452 +8453 +8454 +8455 +8456 +8457 +8458 +8459 +8460 +8461 +8462 +8463 +8464 +8465 +8466 +8467 +8468 +8469 +8470 +8471 +8472 +8473 +8474 +8475 +8476 +8477 +8478 +8479 +8480 +8481 +8482 +8483 +8484 +8485 +8486 +8487 +8488 +8489 +8490 +8491 +8492 +8493 +8494 +8495 +8496 +8497 +8498 +8499 +8500 +8501 +8502 +8503 +8504 +8505 +8506 +8507 +8508 +8509 +8510 +8511 +8512 +8513 +8514 +8515 +8516 +8517 +8518 +8519 +8520 +8521 +8522 +8523 +8524 +8525 +8526 +8527 +8528 +8529 +8530 +8531 +8532 +8533 +8534 +8535 +8536 +8537 +8538 +8539 +8540 +8541 +8542 +8543 +8544 +8545 +8546 +8547 +8548 +8549 +8550 +8551 +8552 +8553 +8554 +8555 +8556 +8557 +8558 +8559 +8560 +8561 +8562 +8563 +8564 +8565 +8566 +8567 +8568 +8569 +8570 +8571 +8572 +8573 +8574 +8575 +8576 +8577 +8578 +8579 +8580 +8581 +8582 +8583 +8584 +8585 +8586 +8587 +8588 +8589 +8590 +8591 +8592 +8593 +8594 +8595 +8596 +8597 +8598 +8599 +8600 +8601 +8602 +8603 +8604 +8605 +8606 +8607 +8608 +8609 +8610 +8611 +8612 +8613 +8614 +8615 +8616 +8617 +8618 +8619 +8620 +8621 +8622 +8623 +8624 +8625 +8626 +8627 +8628 +8629 +8630 +8631 +8632 +8633 +8634 +8635 +8636 +8637 +8638 +8639 +8640 +8641 +8642 +8643 +8644 +8645 +8646 +8647 +8648 +8649 +8650 +8651 +8652 +8653 +8654 +8655 +8656 +8657 +8658 +8659 +8660 +8661 +8662 +8663 +8664 +8665 +8666 +8667 +8668 +8669 +8670 +8671 +8672 +8673 +8674 +8675 +8676 +8677 +8678 +8679 +8680 +8681 +8682 +8683 +8684 +8685 +8686 +8687 +8688 +8689 +8690 +8691 +8692 +8693 +8694 +8695 +8696 +8697 +8698 +8699 +8700 +8701 +8702 +8703 +8704 +8705 +8706 +8707 +8708 +8709 +8710 +8711 +8712 +8713 +8714 +8715 +8716 +8717 +8718 +8719 +8720 +8721 +8722 +8723 +8724 +8725 +8726 +8727 +8728 +8729 +8730 +8731 +8732 +8733 +8734 +8735 +8736 +8737 +8738 +8739 +8740 +8741 +8742 +8743 +8744 +8745 +8746 +8747 +8748 +8749 +8750 +8751 +8752 +8753 +8754 +8755 +8756 +8757 +8758 +8759 +8760 +8761 +8762 +8763 +8764 +8765 +8766 +8767 +8768 +8769 +8770 +8771 +8772 +8773 +8774 +8775 +8776 +8777 +8778 +8779 +8780 +8781 +8782 +8783 +8784 +8785 +8786 +8787 +8788 +8789 +8790 +8791 +8792 +8793 +8794 +8795 +8796 +8797 +8798 +8799 +8800 +8801 +8802 +8803 +8804 +8805 +8806 +8807 +8808 +8809 +8810 +8811 +8812 +8813 +8814 +8815 +8816 +8817 +8818 +8819 +8820 +8821 +8822 +8823 +8824 +8825 +8826 +8827 +8828 +8829 +8830 +8831 +8832 +8833 +8834 +8835 +8836 +8837 +8838 +8839 +8840 +8841 +8842 +8843 +8844 +8845 +8846 +8847 +8848 +8849 +8850 +8851 +8852 +8853 +8854 +8855 +8856 +8857 +8858 +8859 +8860 +8861 +8862 +8863 +8864 +8865 +8866 +8867 +8868 +8869 +8870 +8871 +8872 +8873 +8874 +8875 +8876 +8877 +8878 +8879 +8880 +8881 +8882 +8883 +8884 +8885 +8886 +8887 +8888 +8889 +8890 +8891 +8892 +8893 +8894 +8895 +8896 +8897 +8898 +8899 +8900 +8901 +8902 +8903 +8904 +8905 +8906 +8907 +8908 +8909 +8910 +8911 +8912 +8913 +8914 +8915 +8916 +8917 +8918 +8919 +8920 +8921 +8922 +8923 +8924 +8925 +8926 +8927 +8928 +8929 +8930 +8931 +8932 +8933 +8934 +8935 +8936 +8937 +8938 +8939 +8940 +8941 +8942 +8943 +8944 +8945 +8946 +8947 +8948 +8949 +8950 +8951 +8952 +8953 +8954 +8955 +8956 +8957 +8958 +8959 +8960 +8961 +8962 +8963 +8964 +8965 +8966 +8967 +8968 +8969 +8970 +8971 +8972 +8973 +8974 +8975 +8976 +8977 +8978 +8979 +8980 +8981 +8982 +8983 +8984 +8985 +8986 +8987 +8988 +8989 +8990 +8991 +8992 +8993 +8994 +8995 +8996 +8997 +8998 +8999 +9000 +9001 +9002 +9003 +9004 +9005 +9006 +9007 +9008 +9009 +9010 +9011 +9012 +9013 +9014 +9015 +9016 +9017 +9018 +9019 +9020 +9021 +9022 +9023 +9024 +9025 +9026 +9027 +9028 +9029 +9030 +9031 +9032 +9033 +9034 +9035 +9036 +9037 +9038 +9039 +9040 +9041 +9042 +9043 +9044 +9045 +9046 +9047 +9048 +9049 +9050 +9051 +9052 +9053 +9054 +9055 +9056 +9057 +9058 +9059 +9060 +9061 +9062 +9063 +9064 +9065 +9066 +9067 +9068 +9069 +9070 +9071 +9072 +9073 +9074 +9075 +9076 +9077 +9078 +9079 +9080 +9081 +9082 +9083 +9084 +9085 +9086 +9087 +9088 +9089 +9090 +9091 +9092 +9093 +9094 +9095 +9096 +9097 +9098 +9099 +9100 +9101 +9102 +9103 +9104 +9105 +9106 +9107 +9108 +9109 +9110 +9111 +9112 +9113 +9114 +9115 +9116 +9117 +9118 +9119 +9120 +9121 +9122 +9123 +9124 +9125 +9126 +9127 +9128 +9129 +9130 +9131 +9132 +9133 +9134 +9135 +9136 +9137 +9138 +9139 +9140 +9141 +9142 +9143 +9144 +9145 +9146 +9147 +9148 +9149 +9150 +9151 +9152 +9153 +9154 +9155 +9156 +9157 +9158 +9159 +9160 +9161 +9162 +9163 +9164 +9165 +9166 +9167 +9168 +9169 +9170 +9171 +9172 +9173 +9174 +9175 +9176 +9177 +9178 +9179 +9180 +9181 +9182 +9183 +9184 +9185 +9186 +9187 +9188 +9189 +9190 +9191 +9192 +9193 +9194 +9195 +9196 +9197 +9198 +9199 +9200 +9201 +9202 +9203 +9204 +9205 +9206 +9207 +9208 +9209 +9210 +9211 +9212 +9213 +9214 +9215 +9216 +9217 +9218 +9219 +9220 +9221 +9222 +9223 +9224 +9225 +9226 +9227 +9228 +9229 +9230 +9231 +9232 +9233 +9234 +9235 +9236 +9237 +9238 +9239 +9240 +9241 +9242 +9243 +9244 +9245 +9246 +9247 +9248 +9249 +9250 +9251 +9252 +9253 +9254 +9255 +9256 +9257 +9258 +9259 +9260 +9261 +9262 +9263 +9264 +9265 +9266 +9267 +9268 +9269 +9270 +9271 +9272 +9273 +9274 +9275 +9276 +9277 +9278 +9279 +9280 +9281 +9282 +9283 +9284 +9285 +9286 +9287 +9288 +9289 +9290 +9291 +9292 +9293 +9294 +9295 +9296 +9297 +9298 +9299 +9300 +9301 +9302 +9303 +9304 +9305 +9306 +9307 +9308 +9309 +9310 +9311 +9312 +9313 +9314 +9315 +9316 +9317 +9318 +9319 +9320 +9321 +9322 +9323 +9324 +9325 +9326 +9327 +9328 +9329 +9330 +9331 +9332 +9333 +9334 +9335 +9336 +9337 +9338 +9339 +9340 +9341 +9342 +9343 +9344 +9345 +9346 +9347 +9348 +9349 +9350 +9351 +9352 +9353 +9354 +9355 +9356 +9357 +9358 +9359 +9360 +9361 +9362 +9363 +9364 +9365 +9366 +9367 +9368 +9369 +9370 +9371 +9372 +9373 +9374 +9375 +9376 +9377 +9378 +9379 +9380 +9381 +9382 +9383 +9384 +9385 +9386 +9387 +9388 +9389 +9390 +9391 +9392 +9393 +9394 +9395 +9396 +9397 +9398 +9399 +9400 +9401 +9402 +9403 +9404 +9405 +9406 +9407 +9408 +9409 +9410 +9411 +9412 +9413 +9414 +9415 +9416 +9417 +9418 +9419 +9420 +9421 +9422 +9423 +9424 +9425 +9426 +9427 +9428 +9429 +9430 +9431 +9432 +9433 +9434 +9435 +9436 +9437 +9438 +9439 +9440 +9441 +9442 +9443 +9444 +9445 +9446 +9447 +9448 +9449 +9450 +9451 +9452 +9453 +9454 +9455 +9456 +9457 +9458 +9459 +9460 +9461 +9462 +9463 +9464 +9465 +9466 +9467 +9468 +9469 +9470 +9471 +9472 +9473 +9474 +9475 +9476 +9477 +9478 +9479 +9480 +9481 +9482 +9483 +9484 +9485 +9486 +9487 +9488 +9489 +9490 +9491 +9492 +9493 +9494 +9495 +9496 +9497 +9498 +9499 +9500 +9501 +9502 +9503 +9504 +9505 +9506 +9507 +9508 +9509 +9510 +9511 +9512 +9513 +9514 +9515 +9516 +9517 +9518 +9519 +9520 +9521 +9522 +9523 +9524 +9525 +9526 +9527 +9528 +9529 +9530 +9531 +9532 +9533 +9534 +9535 +9536 +9537 +9538 +9539 +9540 +9541 +9542 +9543 +9544 +9545 +9546 +9547 +9548 +9549 +9550 +9551 +9552 +9553 +9554 +9555 +9556 +9557 +9558 +9559 +9560 +9561 +9562 +9563 +9564 +9565 +9566 +9567 +9568 +9569 +9570 +9571 +9572 +9573 +9574 +9575 +9576 +9577 +9578 +9579 +9580 +9581 +9582 +9583 +9584 +9585 +9586 +9587 +9588 +9589 +9590 +9591 +9592 +9593 +9594 +9595 +9596 +9597 +9598 +9599 +9600 +9601 +9602 +9603 +9604 +9605 +9606 +9607 +9608 +9609 +9610 +9611 +9612 +9613 +9614 +9615 +9616 +9617 +9618 +9619 +9620 +9621 +9622 +9623 +9624 +9625 +9626 +9627 +9628 +9629 +9630 +9631 +9632 +9633 +9634 +9635 +9636 +9637 +9638 +9639 +9640 +9641 +9642 +9643 +9644 +9645 +9646 +9647 +9648 +9649 +9650 +9651 +9652 +9653 +9654 +9655 +9656 +9657 +9658 +9659 +9660 +9661 +9662 +9663 +9664 +9665 +9666 +9667 +9668 +9669 +9670 +9671 +9672 +9673 +9674 +9675 +9676 +9677 +9678 +9679 +9680 +9681 +9682 +9683 +9684 +9685 +9686 +9687 +9688 +9689 +9690 +9691 +9692 +9693 +9694 +9695 +9696 +9697 +9698 +9699 +9700 +9701 +9702 +9703 +9704 +9705 +9706 +9707 +9708 +9709 +9710 +9711 +9712 +9713 +9714 +9715 +9716 +9717 +9718 +9719 +9720 +9721 +9722 +9723 +9724 +9725 +9726 +9727 +9728 +9729 +9730 +9731 +9732 +9733 +9734 +9735 +9736 +9737 +9738 +9739 +9740 +9741 +9742 +9743 +9744 +9745 +9746 +9747 +9748 +9749 +9750 +9751 +9752 +9753 +9754 +9755 +9756 +9757 +9758 +9759 +9760 +9761 +9762 +9763 +9764 +9765 +9766 +9767 +9768 +9769 +9770 +9771 +9772 +9773 +9774 +9775 +9776 +9777 +9778 +9779 +9780 +9781 +9782 +9783 +9784 +9785 +9786 +9787 +9788 +9789 +9790 +9791 +9792 +9793 +9794 +9795 +9796 +9797 +9798 +9799 +9800 +9801 +9802 +9803 +9804 +9805 +9806 +9807 +9808 +9809 +9810 +9811 +9812 +9813 +9814 +9815 +9816 +9817 +9818 +9819 +9820 +9821 +9822 +9823 +9824 +9825 +9826 +9827 +9828 +9829 +9830 +9831 +9832 +9833 +9834 +9835 +9836 +9837 +9838 +9839 +9840 +9841 +9842 +9843 +9844 +9845 +9846 +9847 +9848 +9849 +9850 +9851 +9852 +9853 +9854 +9855 +9856 +9857 +9858 +9859 +9860 +9861 +9862 +9863 +9864 +9865 +9866 +9867 +9868 +9869 +9870 +9871 +9872 +9873 +9874 +9875 +9876 +9877 +9878 +9879 +9880 +9881 +9882 +9883 +9884 +9885 +9886 +9887 +9888 +9889 +9890 +9891 +9892 +9893 +9894 +9895 +9896 +9897 +9898 +9899 +9900 +9901 +9902 +9903 +9904 +9905 +9906 +9907 +9908 +9909 +9910 +9911 +9912 +9913 +9914 +9915 +9916 +9917 +9918 +9919 +9920 +9921 +9922 +9923 +9924 +9925 +9926 +9927 +9928 +9929 +9930 +9931 +9932 +9933 +9934 +9935 +9936 +9937 +9938 +9939 +9940 +9941 +9942 +9943 +9944 +9945 +9946 +9947 +9948 +9949 +9950 +9951 +9952 +9953 +9954 +9955 +9956 +9957 +9958 +9959 +9960 +9961 +9962 +9963 +9964 +9965 +9966 +9967 +9968 +9969 +9970 +9971 +9972 +9973 +9974 +9975 +9976 +9977 +9978 +9979 +9980 +9981 +9982 +9983 +9984 +9985 +9986 +9987 +9988 +9989 +9990 +9991 +9992 +9993 +9994 +9995 +9996 +9997 +9998 +9999 +10000 +10001 +10002 +10003 +10004 +10005 +10006 +10007 +10008 +10009 +10010 +10011 +10012 +10013 +10014 +10015 +10016 +10017 +10018 +10019 +10020 +10021 +10022 +10023 +10024 +10025 +10026 +10027 +10028 +10029 +10030 +10031 +10032 +10033 +10034 +10035 +10036 +10037 +10038 +10039 +10040 +10041 +10042 +10043 +10044 +10045 +10046 +10047 +10048 +10049 +10050 +10051 +10052 +10053 +10054 +10055 +10056 +10057 +10058 +10059 +10060 +10061 +10062 +10063 +10064 +10065 +10066 +10067 +10068 +10069 +10070 +10071 +10072 +10073 +10074 +10075 +10076 +10077 +10078 +10079 +10080 +10081 +10082 +10083 +10084 +10085 +10086 +10087 +10088 +10089 +10090 +10091 +10092 +10093 +10094 +10095 +10096 +10097 +10098 +10099 +10100 +10101 +10102 +10103 +10104 +10105 +10106 +10107 +10108 +10109 +10110 +10111 +10112 +10113 +10114 +10115 +10116 +10117 +10118 +10119 +10120 +10121 +10122 +10123 +10124 +10125 +10126 +10127 +10128 +10129 +10130 +10131 +10132 +10133 +10134 +10135 +10136 +10137 +10138 +10139 +10140 +10141 +10142 +10143 +10144 +10145 +10146 +10147 +10148 +10149 +10150 +10151 +10152 +10153 +10154 +10155 +10156 +10157 +10158 +10159 +10160 +10161 +10162 +10163 +10164 +10165 +10166 +10167 +10168 +10169 +10170 +10171 +10172 +10173 +10174 +10175 +10176 +10177 +10178 +10179 +10180 +10181 +10182 +10183 +10184 +10185 +10186 +10187 +10188 +10189 +10190 +10191 +10192 +10193 +10194 +10195 +10196 +10197 +10198 +10199 +10200 +10201 +10202 +10203 +10204 +10205 +10206 +10207 +10208 +10209 +10210 +10211 +10212 +10213 +10214 +10215 +10216 +10217 +10218 +10219 +10220 +10221 +10222 +10223 +10224 +10225 +10226 +10227 +10228 +10229 +10230 +10231 +10232 +10233 +10234 +10235 +10236 +10237 +10238 +10239 +10240 +10241 +10242 +10243 +10244 +10245 +10246 +10247 +10248 +10249 +10250 +10251 +10252 +10253 +10254 +10255 +10256 +10257 +10258 +10259 +10260 +10261 +10262 +10263 +10264 +10265 +10266 +10267 +10268 +10269 +10270 +10271 +10272 +10273 +10274 +10275 +10276 +10277 +10278 +10279 +10280 +10281 +10282 +10283 +10284 +10285 +10286 +10287 +10288 +10289 +10290 +10291 +10292 +10293 +10294 +10295 +10296 +10297 +10298 +10299 +10300 +10301 +10302 +10303 +10304 +10305 +10306 +10307 +10308 +10309 +10310 +10311 +10312 +10313 +10314 +10315 +10316 +10317 +10318 +10319 +10320 +10321 +10322 +10323 +10324 +10325 +10326 +10327 +10328 +10329 +10330 +10331 +10332 +10333 +10334 +10335 +10336 +10337 +10338 +10339 +10340 +10341 +10342 +10343 +10344 +10345 +10346 +10347 +10348 +10349 +10350 +10351 +10352 +10353 +10354 +10355 +10356 +10357 +10358 +10359 +10360 +10361 +10362 +10363 +10364 +10365 +10366 +10367 +10368 +10369 +10370 +10371 +10372 +10373 +10374 +10375 +10376 +10377 +10378 +10379 +10380 +10381 +10382 +10383 +10384 +10385 +10386 +10387 +10388 +10389 +10390 +10391 +10392 +10393 +10394 +10395 +10396 +10397 +10398 +10399 +10400 +10401 +10402 +10403 +10404 +10405 +10406 +10407 +10408 +10409 +10410 +10411 +10412 +10413 +10414 +10415 +10416 +10417 +10418 +10419 +10420 +10421 +10422 +10423 +10424 +10425 +10426 +10427 +10428 +10429 +10430 +10431 +10432 +10433 +10434 +10435 +10436 +10437 +10438 +10439 +10440 +10441 +10442 +10443 +10444 +10445 +10446 +10447 +10448 +10449 +10450 +10451 +10452 +10453 +10454 +10455 +10456 +10457 +10458 +10459 +10460 +10461 +10462 +10463 +10464 +10465 +10466 +10467 +10468 +10469 +10470 +10471 +10472 +10473 +10474 +10475 +10476 +10477 +10478 +10479 +10480 +10481 +10482 +10483 +10484 +10485 +10486 +10487 +10488 +10489 +10490 +10491 +10492 +10493 +10494 +10495 +10496 +10497 +10498 +10499 +10500 +10501 +10502 +10503 +10504 +10505 +10506 +10507 +10508 +10509 +10510 +10511 +10512 +10513 +10514 +10515 +10516 +10517 +10518 +10519 +10520 +10521 +10522 +10523 +10524 +10525 +10526 +10527 +10528 +10529 +10530 +10531 +10532 +10533 +10534 +10535 +10536 +10537 +10538 +10539 +10540 +10541 +10542 +10543 +10544 +10545 +10546 +10547 +10548 +10549 +10550 +10551 +10552 +10553 +10554 +10555 +10556 +10557 +10558 +10559 +10560 +10561 +10562 +10563 +10564 +10565 +10566 +10567 +10568 +10569 +10570 +10571 +10572 +10573 +10574 +10575 +10576 +10577 +10578 +10579 +10580 +10581 +10582 +10583 +10584 +10585 +10586 +10587 +10588 +10589 +10590 +10591 +10592 +10593 +10594 +10595 +10596 +10597 +10598 +10599 +10600 +10601 +10602 +10603 +10604 +10605 +10606 +10607 +10608 +10609 +10610 +10611 +10612 +10613 +10614 +10615 +10616 +10617 +10618 +10619 +10620 +10621 +10622 +10623 +10624 +10625 +10626 +10627 +10628 +10629 +10630 +10631 +10632 +10633 +10634 +10635 +10636 +10637 +10638 +10639 +10640 +10641 +10642 +10643 +10644 +10645 +10646 +10647 +10648 +10649 +10650 +10651 +10652 +10653 +10654 +10655 +10656 +10657 +10658 +10659 +10660 +10661 +10662 +10663 +10664 +10665 +10666 +10667 +10668 +10669 +10670 +10671 +10672 +10673 +10674 +10675 +10676 +10677 +10678 +10679 +10680 +10681 +10682 +10683 +10684 +10685 +10686 +10687 +10688 +10689 +10690 +10691 +10692 +10693 +10694 +10695 +10696 +10697 +10698 +10699 +10700 +10701 +10702 +10703 +10704 +10705 +10706 +10707 +10708 +10709 +10710 +10711 +10712 +10713 +10714 +10715 +10716 +10717 +10718 +10719 +10720 +10721 +10722 +10723 +10724 +10725 +10726 +10727 +10728 +10729 +10730 +10731 +10732 +10733 +10734 +10735 +10736 +10737 +10738 +10739 +10740 +10741 +10742 +10743 +10744 +10745 +10746 +10747 +10748 +10749 +10750 +10751 +10752 +10753 +10754 +10755 +10756 +10757 +10758 +10759 +10760 +10761 +10762 +10763 +10764 +10765 +10766 +10767 +10768 +10769 +10770 +10771 +10772 +10773 +10774 +10775 +10776 +10777 +10778 +10779 +10780 +10781 +10782 +10783 +10784 +10785 +10786 +10787 +10788 +10789 +10790 +10791 +10792 +10793 +10794 +10795 +10796 +10797 +10798 +10799 +10800 +10801 +10802 +10803 +10804 +10805 +10806 +10807 +10808 +10809 +10810 +10811 +10812 +10813 +10814 +10815 +10816 +10817 +10818 +10819 +10820 +10821 +10822 +10823 +10824 +10825 +10826 +10827 +10828 +10829 +10830 +10831 +10832 +10833 +10834 +10835 +10836 +10837 +10838 +10839 +10840 +10841 +10842 +10843 +10844 +10845 +10846 +10847 +10848 +10849 +10850 +10851 +10852 +10853 +10854 +10855 +10856 +10857 +10858 +10859 +10860 +10861 +10862 +10863 +10864 +10865 +10866 +10867 +10868 +10869 +10870 +10871 +10872 +10873 +10874 +10875 +10876 +10877 +10878 +10879 +10880 +10881 +10882 +10883 +10884 +10885 +10886 +10887 +10888 +10889 +10890 +10891 +10892 +10893 +10894 +10895 +10896 +10897 +10898 +10899 +10900 +10901 +10902 +10903 +10904 +10905 +10906 +10907 +10908 +10909 +10910 +10911 +10912 +10913 +10914 +10915 +10916 +10917 +10918 +10919 +10920 +10921 +10922 +10923 +10924 +10925 +10926 +10927 +10928 +10929 +10930 +10931 +10932 +10933 +10934 +10935 +10936 +10937 +10938 +10939 +10940 +10941 +10942 +10943 +10944 +10945 +10946 +10947 +10948 +10949 +10950 +10951 +10952 +10953 +10954 +10955 +10956 +10957 +10958 +10959 +10960 +10961 +10962 +10963 +10964 +10965 +10966 +10967 +10968 +10969 +10970 +10971 +10972 +10973 +10974 +10975 +10976 +10977 +10978 +10979 +10980 +10981 +10982 +10983 +10984 +10985 +10986 +10987 +10988 +10989 +10990 +10991 +10992 +10993 +10994 +10995 +10996 +10997 +10998 +10999 +11000 +11001 +11002 +11003 +11004 +11005 +11006 +11007 +11008 +11009 +11010 +11011 +11012 +11013 +11014 +11015 +11016 +11017 +11018 +11019 +11020 +11021 +11022 +11023 +11024 +11025 +11026 +11027 +11028 +11029 +11030 +11031 +11032 +11033 +11034 +11035 +11036 +11037 +11038 +11039 +11040 +11041 +11042 +11043 +11044 +11045 +11046 +11047 +11048 +11049 +11050 +11051 +11052 +11053 +11054 +11055 +11056 +11057 +11058 +11059 +11060 +11061 +11062 +11063 +11064 +11065 +11066 +11067 +11068 +11069 +11070 +11071 +11072 +11073 +11074 +11075 +11076 +11077 +11078 +11079 +11080 +11081 +11082 +11083 +11084 +11085 +11086 +11087 +11088 +11089 +11090 +11091 +11092 +11093 +11094 +11095 +11096 +11097 +11098 +11099 +11100 +11101 +11102 +11103 +11104 +11105 +11106 +11107 +11108 +11109 +11110 +11111 +11112 +11113 +11114 +11115 +11116 +11117 +11118 +11119 +11120 +11121 +11122 +11123 +11124 +11125 +11126 +11127 +11128 +11129 +11130 +11131 +11132 +11133 +11134 +11135 +11136 +11137 +11138 +11139 +11140 +11141 +11142 +11143 +11144 +11145 +11146 +11147 +11148 +11149 +11150 +11151 +11152 +11153 +11154 +11155 +11156 +11157 +11158 +11159 +11160 +11161 +11162 +11163 +11164 +11165 +11166 +11167 +11168 +11169 +11170 +11171 +11172 +11173 +11174 +11175 +11176 +11177 +11178 +11179 +11180 +11181 +11182 +11183 +11184 +11185 +11186 +11187 +11188 +11189 +11190 +11191 +11192 +11193 +11194 +11195 +11196 +11197 +11198 +11199 +11200 +11201 +11202 +11203 +11204 +11205 +11206 +11207 +11208 +11209 +11210 +11211 +11212 +11213 +11214 +11215 +11216 +11217 +11218 +11219 +11220 +11221 +11222 +11223 +11224 +11225 +11226 +11227 +11228 +11229 +11230 +11231 +11232 +11233 +11234 +11235 +11236 +11237 +11238 +11239 +11240 +11241 +11242 +11243 +11244 +11245 +11246 +11247 +11248 +11249 +11250 +11251 +11252 +11253 +11254 +11255 +11256 +11257 +11258 +11259 +11260 +11261 +11262 +11263 +11264 +11265 +11266 +11267 +11268 +11269 +11270 +11271 +11272 +11273 +11274 +11275 +11276 +11277 +11278 +11279 +11280 +11281 +11282 +11283 +11284 +11285 +11286 +11287 +11288 +11289 +11290 +11291 +11292 +11293 +11294 +11295 +11296 +11297 +11298 +11299 +11300 +11301 +11302 +11303 +11304 +11305 +11306 +11307 +11308 +11309 +11310 +11311 +11312 +11313 +11314 +11315 +11316 +11317 +11318 +11319 +11320 +11321 +11322 +11323 +11324 +11325 +11326 +11327 +11328 +11329 +11330 +11331 +11332 +11333 +11334 +11335 +11336 +11337 +11338 +11339 +11340 +11341 +11342 +11343 +11344 +11345 +11346 +11347 +11348 +11349 +11350 +11351 +11352 +11353 +11354 +11355 +11356 +11357 +11358 +11359 +11360 +11361 +11362 +11363 +11364 +11365 +11366 +11367 +11368 +11369 +11370 +11371 +11372 +11373 +11374 +11375 +11376 +11377 +11378 +11379 +11380 +11381 +11382 +11383 +11384 +11385 +11386 +11387 +11388 +11389 +11390 +11391 +11392 +11393 +11394 +11395 +11396 +11397 +11398 +11399 +11400 +11401 +11402 +11403 +11404 +11405 +11406 +11407 +11408 +11409 +11410 +11411 +11412 +11413 +11414 +11415 +11416 +11417 +11418 +11419 +11420 +11421 +11422 +11423 +11424 +11425 +11426 +11427 +11428 +11429 +11430 +11431 +11432 +11433 +11434 +11435 +11436 +11437 +11438 +11439 +11440 +11441 +11442 +11443 +11444 +11445 +11446 +11447 +11448 +11449 +11450 +11451 +11452 +11453 +11454 +11455 +11456 +11457 +11458 +11459 +11460 +11461 +11462 +11463 +11464 +11465 +11466 +11467 +11468 +11469 +11470 +11471 +11472 +11473 +11474 +11475 +11476 +11477 +11478 +11479 +11480 +11481 +11482 +11483 +11484 +11485 +11486 +11487 +11488 +11489 +11490 +11491 +11492 +11493 +11494 +11495 +11496 +11497 +11498 +11499 +11500 +11501 +11502 +11503 +11504 +11505 +11506 +11507 +11508 +11509 +11510 +11511 +11512 +11513 +11514 +11515 +11516 +11517 +11518 +11519 +11520 +11521 +11522 +11523 +11524 +11525 +11526 +11527 +11528 +11529 +11530 +11531 +11532 +11533 +11534 +11535 +11536 +11537 +11538 +11539 +11540 +11541 +11542 +11543 +11544 +11545 +11546 +11547 +11548 +11549 +11550 +11551 +11552 +11553 +11554 +11555 +11556 +11557 +11558 +11559 +11560 +11561 +11562 +11563 +11564 +11565 +11566 +11567 +11568 +11569 +11570 +11571 +11572 +11573 +11574 +11575 +11576 +11577 +11578 +11579 +11580 +11581 +11582 +11583 +11584 +11585 +11586 +11587 +11588 +11589 +11590 +11591 +11592 +11593 +11594 +11595 +11596 +11597 +11598 +11599 +11600 +11601 +11602 +11603 +11604 +11605 +11606 +11607 +11608 +11609 +11610 +11611 +11612 +11613 +11614 +11615 +11616 +11617 +11618 +11619 +11620 +11621 +11622 +11623 +11624 +11625 +11626 +11627 +11628 +11629 +11630 +11631 +11632 +11633 +11634 +11635 +11636 +11637 +11638 +11639 +11640 +11641 +11642 +11643 +11644 +11645 +11646 +11647 +11648 +11649 +11650 +11651 +11652 +11653 +11654 +11655 +11656 +11657 +11658 +11659 +11660 +11661 +11662 +11663 +11664 +11665 +11666 +11667 +11668 +11669 +11670 +11671 +11672 +11673 +11674 +11675 +11676 +11677 +11678 +11679 +11680 +11681 +11682 +11683 +11684 +11685 +11686 +11687 +11688 +11689 +11690 +11691 +11692 +11693 +11694 +11695 +11696 +11697 +11698 +11699 +11700 +11701 +11702 +11703 +11704 +11705 +11706 +11707 +11708 +11709 +11710 +11711 +11712 +11713 +11714 +11715 +11716 +11717 +11718 +11719 +11720 +11721 +11722 +11723 +11724 +11725 +11726 +11727 +11728 +11729 +11730 +11731 +11732 +11733 +11734 +11735 +11736 +11737 +11738 +11739 +11740 +11741 +11742 +11743 +11744 +11745 +11746 +11747 +11748 +11749 +11750 +11751 +11752 +11753 +11754 +11755 +11756 +11757 +11758 +11759 +11760 +11761 +11762 +11763 +11764 +11765 +11766 +11767 +11768 +11769 +11770 +11771 +11772 +11773 +11774 +11775 +11776 +11777 +11778 +11779 +11780 +11781 +11782 +11783 +11784 +11785 +11786 +11787 +11788 +11789 +11790 +11791 +11792 +11793 +11794 +11795 +11796 +11797 +11798 +11799 +11800 +11801 +11802 +11803 +11804 +11805 +11806 +11807 +11808 +11809 +11810 +11811 +11812 +11813 +11814 +11815 +11816 +11817 +11818 +11819 +11820 +11821 +11822 +11823 +11824 +11825 +11826 +11827 +11828 +11829 +11830 +11831 +11832 +11833 +11834 +11835 +11836 +11837 +11838 +11839 +11840 +11841 +11842 +11843 +11844 +11845 +11846 +11847 +11848 +11849 +11850 +11851 +11852 +11853 +11854 +11855 +11856 +11857 +11858 +11859 +11860 +11861 +11862 +11863 +11864 +11865 +11866 +11867 +11868 +11869 +11870 +11871 +11872 +11873 +11874 +11875 +11876 +11877 +11878 +11879 +11880 +11881 +11882 +11883 +11884 +11885 +11886 +11887 +11888 +11889 +11890 +11891 +11892 +11893 +11894 +11895 +11896 +11897 +11898 +11899 +11900 +11901 +11902 +11903 +11904 +11905 +11906 +11907 +11908 +11909 +11910 +11911 +11912 +11913 +11914 +11915 +11916 +11917 +11918 +11919 +11920 +11921 +11922 +11923 +11924 +11925 +11926 +11927 +11928 +11929 +11930 +11931 +11932 +11933 +11934 +11935 +11936 +11937 +11938 +11939 +11940 +11941 +11942 +11943 +11944 +11945 +11946 +11947 +11948 +11949 +11950 +11951 +11952 +11953 +11954 +11955 +11956 +11957 +11958 +11959 +11960 +11961 +11962 +11963 +11964 +11965 +11966 +11967 +11968 +11969 +11970 +11971 +11972 +11973 +11974 +11975 +11976 +11977 +11978 +11979 +11980 +11981 +11982 +11983 +11984 +11985 +11986 +11987 +11988 +11989 +11990 +11991 +11992 +11993 +11994 +11995 +11996 +11997 +11998 +11999 +12000 +12001 +12002 +12003 +12004 +12005 +12006 +12007 +12008 +12009 +12010 +12011 +12012 +12013 +12014 +12015 +12016 +12017 +12018 +12019 +12020 +12021 +12022 +12023 +12024 +12025 +12026 +12027 +12028 +12029 +12030 +12031 +12032 +12033 +12034 +12035 +12036 +12037 +12038 +12039 +12040 +12041 +12042 +12043 +12044 +12045 +12046 +12047 +12048 +12049 +12050 +12051 +12052 +12053 +12054 +12055 +12056 +12057 +12058 +12059 +12060 +12061 +12062 +12063 +12064 +12065 +12066 +12067 +12068 +12069 +12070 +12071 +12072 +12073 +12074 +12075 +12076 +12077 +12078 +12079 +12080 +12081 +12082 +12083 +12084 +12085 +12086 +12087 +12088 +12089 +12090 +12091 +12092 +12093 +12094 +12095 +12096 +12097 +12098 +12099 +12100 +12101 +12102 +12103 +12104 +12105 +12106 +12107 +12108 +12109 +12110 +12111 +12112 +12113 +12114 +12115 +12116 +12117 +12118 +12119 +12120 +12121 +12122 +12123 +12124 +12125 +12126 +12127 +12128 +12129 +12130 +12131 +12132 +12133 +12134 +12135 +12136 +12137 +12138 +12139 +12140 +12141 +12142 +12143 +12144 +12145 +12146 +12147 +12148 +12149 +12150 +12151 +12152 +12153 +12154 +12155 +12156 +12157 +12158 +12159 +12160 +12161 +12162 +12163 +12164 +12165 +12166 +12167 +12168 +12169 +12170 +12171 +12172 +12173 +12174 +12175 +12176 +12177 +12178 +12179 +12180 +12181 +12182 +12183 +12184 +12185 +12186 +12187 +12188 +12189 +12190 +12191 +12192 +12193 +12194 +12195 +12196 +12197 +12198 +12199 +12200 +12201 +12202 +12203 +12204 +12205 +12206 +12207 +12208 +12209 +12210 +12211 +12212 +12213 +12214 +12215 +12216 +12217 +12218 +12219 +12220 +12221 +12222 +12223 +12224 +12225 +12226 +12227 +12228 +12229 +12230 +12231 +12232 +12233 +12234 +12235 +12236 +12237 +12238 +12239 +12240 +12241 +12242 +12243 +12244 +12245 +12246 +12247 +12248 +12249 +12250 +12251 +12252 +12253 +12254 +12255 +12256 +12257 +12258 +12259 +12260 +12261 +12262 +12263 +12264 +12265 +12266 +12267 +12268 +12269 +12270 +12271 +12272 +12273 +12274 +12275 +12276 +12277 +12278 +12279 +12280 +12281 +12282 +12283 +12284 +12285 +12286 +12287 +12288 +12289 +12290 +12291 +12292 +12293 +12294 +12295 +12296 +12297 +12298 +12299 +12300 +12301 +12302 +12303 +12304 +12305 +12306 +12307 +12308 +12309 +12310 +12311 +12312 +12313 +12314 +12315 +12316 +12317 +12318 +12319 +12320 +12321 +12322 +12323 +12324 +12325 +12326 +12327 +12328 +12329 +12330 +12331 +12332 +12333 +12334 +12335 +12336 +12337 +12338 +12339 +12340 +12341 +12342 +12343 +12344 +12345 +12346 +12347 +12348 +12349 +12350 +12351 +12352 +12353 +12354 +12355 +12356 +12357 +12358 +12359 +12360 +12361 +12362 +12363 +12364 +12365 +12366 +12367 +12368 +12369 +12370 +12371 +12372 +12373 +12374 +12375 +12376 +12377 +12378 +12379 +12380 +12381 +12382 +12383 +12384 +12385 +12386 +12387 +12388 +12389 +12390 +12391 +12392 +12393 +12394 +12395 +12396 +12397 +12398 +12399 +12400 +12401 +12402 +12403 +12404 +12405 +12406 +12407 +12408 +12409 +12410 +12411 +12412 +12413 +12414 +12415 +12416 +12417 +12418 +12419 +12420 +12421 +12422 +12423 +12424 +12425 +12426 +12427 +12428 +12429 +12430 +12431 +12432 +12433 +12434 +12435 +12436 +12437 +12438 +12439 +12440 +12441 +12442 +12443 +12444 +12445 +12446 +12447 +12448 +12449 +12450 +12451 +12452 +12453 +12454 +12455 +12456 +12457 +12458 +12459 +12460 +12461 +12462 +12463 +12464 +12465 +12466 +12467 +12468 +12469 +12470 +12471 +12472 +12473 +12474 +12475 +12476 +12477 +12478 +12479 +12480 +12481 +12482 +12483 +12484 +12485 +12486 +12487 +12488 +12489 +12490 +12491 +12492 +12493 +12494 +12495 +12496 +12497 +12498 +12499 +12500 +12501 +12502 +12503 +12504 +12505 +12506 +12507 +12508 +12509 +12510 +12511 +12512 +12513 +12514 +12515 +12516 +12517 +12518 +12519 +12520 +12521 +12522 +12523 +12524 +12525 +12526 +12527 +12528 +12529 +12530 +12531 +12532 +12533 +12534 +12535 +12536 +12537 +12538 +12539 +12540 +12541 +12542 +12543 +12544 +12545 +12546 +12547 +12548 +12549 +12550 +12551 +12552 +12553 +12554 +12555 +12556 +12557 +12558 +12559 +12560 +12561 +12562 +12563 +12564 +12565 +12566 +12567 +12568 +12569 +12570 +12571 +12572 +12573 +12574 +12575 +12576 +12577 +12578 +12579 +12580 +12581 +12582 +12583 +12584 +12585 +12586 +12587 +12588 +12589 +12590 +12591 +12592 +12593 +12594 +12595 +12596 +12597 +12598 +12599 +12600 +12601 +12602 +12603 +12604 +12605 +12606 +12607 +12608 +12609 +12610 +12611 +12612 +12613 +12614 +12615 +12616 +12617 +12618 +12619 +12620 +12621 +12622 +12623 +12624 +12625 +12626 +12627 +12628 +12629 +12630 +12631 +12632 +12633 +12634 +12635 +12636 +12637 +12638 +12639 +12640 +12641 +12642 +12643 +12644 +12645 +12646 +12647 +12648 +12649 +12650 +12651 +12652 +12653 +12654 +12655 +12656 +12657 +12658 +12659 +12660 +12661 +12662 +12663 +12664 +12665 +12666 +12667 +12668 +12669 +12670 +12671 +12672 +12673 +12674 +12675 +12676 +12677 +12678 +12679 +12680 +12681 +12682 +12683 +12684 +12685 +12686 +12687 +12688 +12689 +12690 +12691 +12692 +12693 +12694 +12695 +12696 +12697 +12698 +12699 +12700 +12701 +12702 +12703 +12704 +12705 +12706 +12707 +12708 +12709 +12710 +12711 +12712 +12713 +12714 +12715 +12716 +12717 +12718 +12719 +12720 +12721 +12722 +12723 +12724 +12725 +12726 +12727 +12728 +12729 +12730 +12731 +12732 +12733 +12734 +12735 +12736 +12737 +12738 +12739 +12740 +12741 +12742 +12743 +12744 +12745 +12746 +12747 +12748 +12749 +12750 +12751 +12752 +12753 +12754 +12755 +12756 +12757 +12758 +12759 +12760 +12761 +12762 +12763 +12764 +12765 +12766 +12767 +12768 +12769 +12770 +12771 +12772 +12773 +12774 +12775 +12776 +12777 +12778 +12779 +12780 +12781 +12782 +12783 +12784 +12785 +12786 +12787 +12788 +12789 +12790 +12791 +12792 +12793 +12794 +12795 +12796 +12797 +12798 +12799 +12800 +12801 +12802 +12803 +12804 +12805 +12806 +12807 +12808 +12809 +12810 +12811 +12812 +12813 +12814 +12815 +12816 +12817 +12818 +12819 +12820 +12821 +12822 +12823 +12824 +12825 +12826 +12827 +12828 +12829 +12830 +12831 +12832 +12833 +12834 +12835 +12836 +12837 +12838 +12839 +12840 +12841 +12842 +12843 +12844 +12845 +12846 +12847 +12848 +12849 +12850 +12851 +12852 +12853 +12854 +12855 +12856 +12857 +12858 +12859 +12860 +12861 +12862 +12863 +12864 +12865 +12866 +12867 +12868 +12869 +12870 +12871 +12872 +12873 +12874 +12875 +12876 +12877 +12878 +12879 +12880 +12881 +12882 +12883 +12884 +12885 +12886 +12887 +12888 +12889 +12890 +12891 +12892 +12893 +12894 +12895 +12896 +12897 +12898 +12899 +12900 +12901 +12902 +12903 +12904 +12905 +12906 +12907 +12908 +12909 +12910 +12911 +12912 +12913 +12914 +12915 +12916 +12917 +12918 +12919 +12920 +12921 +12922 +12923 +12924 +12925 +12926 +12927 +12928 +12929 +12930 +12931 +12932 +12933 +12934 +12935 +12936 +12937 +12938 +12939 +12940 +12941 +12942 +12943 +12944 +12945 +12946 +12947 +12948 +12949 +12950 +12951 +12952 +12953 +12954 +12955 +12956 +12957 +12958 +12959 +12960 +12961 +12962 +12963 +12964 +12965 +12966 +12967 +12968 +12969 +12970 +12971 +12972 +12973 +12974 +12975 +12976 +12977 +12978 +12979 +12980 +12981 +12982 +12983 +12984 +12985 +12986 +12987 +12988 +12989 +12990 +12991 +12992 +12993 +12994 +12995 +12996 +12997 +12998 +12999 +13000 +13001 +13002 +13003 +13004 +13005 +13006 +13007 +13008 +13009 +13010 +13011 +13012 +13013 +13014 +13015 +13016 +13017 +13018 +13019 +13020 +13021 +13022 +13023 +13024 +13025 +13026 +13027 +13028 +13029 +13030 +13031 +13032 +13033 +13034 +13035 +13036 +13037 +13038 +13039 +13040 +13041 +13042 +13043 +13044 +13045 +13046 +13047 +13048 +13049 +13050 +13051 +13052 +13053 +13054 +13055 +13056 +13057 +13058 +13059 +13060 +13061 +13062 +13063 +13064 +13065 +13066 +13067 +13068 +13069 +13070 +13071 +13072 +13073 +13074 +13075 +13076 +13077 +13078 +13079 +13080 +13081 +13082 +13083 +13084 +13085 +13086 +13087 +13088 +13089 +13090 +13091 +13092 +13093 +13094 +13095 +13096 +13097 +13098 +13099 +13100 +13101 +13102 +13103 +13104 +13105 +13106 +13107 +13108 +13109 +13110 +13111 +13112 +13113 +13114 +13115 +13116 +13117 +13118 +13119 +13120 +13121 +13122 +13123 +13124 +13125 +13126 +13127 +13128 +13129 +13130 +13131 +13132 +13133 +13134 +13135 +13136 +13137 +13138 +13139 +13140 +13141 +13142 +13143 +13144 +13145 +13146 +13147 +13148 +13149 +13150 +13151 +13152 +13153 +13154 +13155 +13156 +13157 +13158 +13159 +13160 +13161 +13162 +13163 +13164 +13165 +13166 +13167 +13168 +13169 +13170 +13171 +13172 +13173 +13174 +13175 +13176 +13177 +13178 +13179 +13180 +13181 +13182 +13183 +13184 +13185 +13186 +13187 +13188 +13189 +13190 +13191 +13192 +13193 +13194 +13195 +13196 +13197 +13198 +13199 +13200 +13201 +13202 +13203 +13204 +13205 +13206 +13207 +13208 +13209 +13210 +13211 +13212 +13213 +13214 +13215 +13216 +13217 +13218 +13219 +13220 +13221 +13222 +13223 +13224 +13225 +13226 +13227 +13228 +13229 +13230 +13231 +13232 +13233 +13234 +13235 +13236 +13237 +13238 +13239 +13240 +13241 +13242 +13243 +13244 +13245 +13246 +13247 +13248 +13249 +13250 +13251 +13252 +13253 +13254 +13255 +13256 +13257 +13258 +13259 +13260 +13261 +13262 +13263 +13264 +13265 +13266 +13267 +13268 +13269 +13270 +13271 +13272 +13273 +13274 +13275 +13276 +13277 +13278 +13279 +13280 +13281 +13282 +13283 +13284 +13285 +13286 +13287 +13288 +13289 +13290 +13291 +13292 +13293 +13294 +13295 +13296 +13297 +13298 +13299 +13300 +13301 +13302 +13303 +13304 +13305 +13306 +13307 +13308 +13309 +13310 +13311 +13312 +13313 +13314 +13315 +13316 +13317 +13318 +13319 +13320 +13321 +13322 +13323 +13324 +13325 +13326 +13327 +13328 +13329 +13330 +13331 +13332 +13333 +13334 +13335 +13336 +13337 +13338 +13339 +13340 +13341 +13342 +13343 +13344 +13345 +13346 +13347 +13348 +13349 +13350 +13351 +13352 +13353 +13354 +13355 +13356 +13357 +13358 +13359 +13360 +13361 +13362 +13363 +13364 +13365 +13366 +13367 +13368 +13369 +13370 +13371 +13372 +13373 +13374 +13375 +13376 +13377 +13378 +13379 +13380 +13381 +13382 +13383 +13384 +13385 +13386 +13387 +13388 +13389 +13390 +13391 +13392 +13393 +13394 +13395 +13396 +13397 +13398 +13399 +13400 +13401 +13402 +13403 +13404 +13405 +13406 +13407 +13408 +13409 +13410 +13411 +13412 +13413 +13414 +13415 +13416 +13417 +13418 +13419 +13420 +13421 +13422 +13423 +13424 +13425 +13426 +13427 +13428 +13429 +13430 +13431 +13432 +13433 +13434 +13435 +13436 +13437 +13438 +13439 +13440 +13441 +13442 +13443 +13444 +13445 +13446 +13447 +13448 +13449 +13450 +13451 +13452 +13453 +13454 +13455 +13456 +13457 +13458 +13459 +13460 +13461 +13462 +13463 +13464 +13465 +13466 +13467 +13468 +13469 +13470 +13471 +13472 +13473 +13474 +13475 +13476 +13477 +13478 +13479 +13480 +13481 +13482 +13483 +13484 +13485 +13486 +13487 +13488 +13489 +13490 +13491 +13492 +13493 +13494 +13495 +13496 +13497 +13498 +13499 +13500 +13501 +13502 +13503 +13504 +13505 +13506 +13507 +13508 +13509 +13510 +13511 +13512 +13513 +13514 +13515 +13516 +13517 +13518 +13519 +13520 +13521 +13522 +13523 +13524 +13525 +13526 +13527 +13528 +13529 +13530 +13531 +13532 +13533 +13534 +13535 +13536 +13537 +13538 +13539 +13540 +13541 +13542 +13543 +13544 +13545 +13546 +13547 +13548 +13549 +13550 +13551 +13552 +13553 +13554 +13555 +13556 +13557 +13558 +13559 +13560 +13561 +13562 +13563 +13564 +13565 +13566 +13567 +13568 +13569 +13570 +13571 +13572 +13573 +13574 +13575 +13576 +13577 +13578 +13579 +13580 +13581 +13582 +13583 +13584 +13585 +13586 +13587 +13588 +13589 +13590 +13591 +13592 +13593 +13594 +13595 +13596 +13597 +13598 +13599 +13600 +13601 +13602 +13603 +13604 +13605 +13606 +13607 +13608 +13609 +13610 +13611 +13612 +13613 +13614 +13615 +13616 +13617 +13618 +13619 +13620 +13621 +13622 +13623 +13624 +13625 +13626 +13627 +13628 +13629 +13630 +13631 +13632 +13633 +13634 +13635 +13636 +13637 +13638 +13639 +13640 +13641 +13642 +13643 +13644 +13645 +13646 +13647 +13648 +13649 +13650 +13651 +13652 +13653 +13654 +13655 +13656 +13657 +13658 +13659 +13660 +13661 +13662 +13663 +13664 +13665 +13666 +13667 +13668 +13669 +13670 +13671 +13672 +13673 +13674 +13675 +13676 +13677 +13678 +13679 +13680 +13681 +13682 +13683 +13684 +13685 +13686 +13687 +13688 +13689 +13690 +13691 +13692 +13693 +13694 +13695 +13696 +13697 +13698 +13699 +13700 +13701 +13702 +13703 +13704 +13705 +13706 +13707 +13708 +13709 +13710 +13711 +13712 +13713 +13714 +13715 +13716 +13717 +13718 +13719 +13720 +13721 +13722 +13723 +13724 +13725 +13726 +13727 +13728 +13729 +13730 +13731 +13732 +13733 +13734 +13735 +13736 +13737 +13738 +13739 +13740 +13741 +13742 +13743 +13744 +13745 +13746 +13747 +13748 +13749 +13750 +13751 +13752 +13753 +13754 +13755 +13756 +13757 +13758 +13759 +13760 +13761 +13762 +13763 +13764 +13765 +13766 +13767 +13768 +13769 +13770 +13771 +13772 +13773 +13774 +13775 +13776 +13777 +13778 +13779 +13780 +13781 +13782 +13783 +13784 +13785 +13786 +13787 +13788 +13789 +13790 +13791 +13792 +13793 +13794 +13795 +13796 +13797 +13798 +13799 +13800 +13801 +13802 +13803 +13804 +13805 +13806 +13807 +13808 +13809 +13810 +13811 +13812 +13813 +13814 +13815 +13816 +13817 +13818 +13819 +13820 +13821 +13822 +13823 +13824 +13825 +13826 +13827 +13828 +13829 +13830 +13831 +13832 +13833 +13834 +13835 +13836 +13837 +13838 +13839 +13840 +13841 +13842 +13843 +13844 +13845 +13846 +13847 +13848 +13849 +13850 +13851 +13852 +13853 +13854 +13855 +13856 +13857 +13858 +13859 +13860 +13861 +13862 +13863 +13864 +13865 +13866 +13867 +13868 +13869 +13870 +13871 +13872 +13873 +13874 +13875 +13876 +13877 +13878 +13879 +13880 +13881 +13882 +13883 +13884 +13885 +13886 +13887 +13888 +13889 +13890 +13891 +13892 +13893 +13894 +13895 +13896 +13897 +13898 +13899 +13900 +13901 +13902 +13903 +13904 +13905 +13906 +13907 +13908 +13909 +13910 +13911 +13912 +13913 +13914 +13915 +13916 +13917 +13918 +13919 +13920 +13921 +13922 +13923 +13924 +13925 +13926 +13927 +13928 +13929 +13930 +13931 +13932 +13933 +13934 +13935 +13936 +13937 +13938 +13939 +13940 +13941 +13942 +13943 +13944 +13945 +13946 +13947 +13948 +13949 +13950 +13951 +13952 +13953 +13954 +13955 +13956 +13957 +13958 +13959 +13960 +13961 +13962 +13963 +13964 +13965 +13966 +13967 +13968 +13969 +13970 +13971 +13972 +13973 +13974 +13975 +13976 +13977 +13978 +13979 +13980 +13981 +13982 +13983 +13984 +13985 +13986 +13987 +13988 +13989 +13990 +13991 +13992 +13993 +13994 +13995 +13996 +13997 +13998 +13999 +14000 +14001 +14002 +14003 +14004 +14005 +14006 +14007 +14008 +14009 +14010 +14011 +14012 +14013 +14014 +14015 +14016 +14017 +14018 +14019 +14020 +14021 +14022 +14023 +14024 +14025 +14026 +14027 +14028 +14029 +14030 +14031 +14032 +14033 +14034 +14035 +14036 +14037 +14038 +14039 +14040 +14041 +14042 +14043 +14044 +14045 +14046 +14047 +14048 +14049 +14050 +14051 +14052 +14053 +14054 +14055 +14056 +14057 +14058 +14059 +14060 +14061 +14062 +14063 +14064 +14065 +14066 +14067 +14068 +14069 +14070 +14071 +14072 +14073 +14074 +14075 +14076 +14077 +14078 +14079 +14080 +14081 +14082 +14083 +14084 +14085 +14086 +14087 +14088 +14089 +14090 +14091 +14092 +14093 +14094 +14095 +14096 +14097 +14098 +14099 +14100 +14101 +14102 +14103 +14104 +14105 +14106 +14107 +14108 +14109 +14110 +14111 +14112 +14113 +14114 +14115 +14116 +14117 +14118 +14119 +14120 +14121 +14122 +14123 +14124 +14125 +14126 +14127 +14128 +14129 +14130 +14131 +14132 +14133 +14134 +14135 +14136 +14137 +14138 +14139 +14140 +14141 +14142 +14143 +14144 +14145 +14146 +14147 +14148 +14149 +14150 +14151 +14152 +14153 +14154 +14155 +14156 +14157 +14158 +14159 +14160 +14161 +14162 +14163 +14164 +14165 +14166 +14167 +14168 +14169 +14170 +14171 +14172 +14173 +14174 +14175 +14176 +14177 +14178 +14179 +14180 +14181 +14182 +14183 +14184 +14185 +14186 +14187 +14188 +14189 +14190 +14191 +14192 +14193 +14194 +14195 +14196 +14197 +14198 +14199 +14200 +14201 +14202 +14203 +14204 +14205 +14206 +14207 +14208 +14209 +14210 +14211 +14212 +14213 +14214 +14215 +14216 +14217 +14218 +14219 +14220 +14221 +14222 +14223 +14224 +14225 +14226 +14227 +14228 +14229 +14230 +14231 +14232 +14233 +14234 +14235 +14236 +14237 +14238 +14239 +14240 +14241 +14242 +14243 +14244 +14245 +14246 +14247 +14248 +14249 +14250 +14251 +14252 +14253 +14254 +14255 +14256 +14257 +14258 +14259 +14260 +14261 +14262 +14263 +14264 +14265 +14266 +14267 +14268 +14269 +14270 +14271 +14272 +14273 +14274 +14275 +14276 +14277 +14278 +14279 +14280 +14281 +14282 +14283 +14284 +14285 +14286 +14287 +14288 +14289 +14290 +14291 +14292 +14293 +14294 +14295 +14296 +14297 +14298 +14299 +14300 +14301 +14302 +14303 +14304 +14305 +14306 +14307 +14308 +14309 +14310 +14311 +14312 +14313 +14314 +14315 +14316 +14317 +14318 +14319 +14320 +14321 +14322 +14323 +14324 +14325 +14326 +14327 +14328 +14329 +14330 +14331 +14332 +14333 +14334 +14335 +14336 +14337 +14338 +14339 +14340 +14341 +14342 +14343 +14344 +14345 +14346 +14347 +14348 +14349 +14350 +14351 +14352 +14353 +14354 +14355 +14356 +14357 +14358 +14359 +14360 +14361 +14362 +14363 +14364 +14365 +14366 +14367 +14368 +14369 +14370 +14371 +14372 +14373 +14374 +14375 +14376 +14377 +14378 +14379 +14380 +14381 +14382 +14383 +14384 +14385 +14386 +14387 +14388 +14389 +14390 +14391 +14392 +14393 +14394 +14395 +14396 +14397 +14398 +14399 +14400 +14401 +14402 +14403 +14404 +14405 +14406 +14407 +14408 +14409 +14410 +14411 +14412 +14413 +14414 +14415 +14416 +14417 +14418 +14419 +14420 +14421 +14422 +14423 +14424 +14425 +14426 +14427 +14428 +14429 +14430 +14431 +14432 +14433 +14434 +14435 +14436 +14437 +14438 +14439 +14440 +14441 +14442 +14443 +14444 +14445 +14446 +14447 +14448 +14449 +14450 +14451 +14452 +14453 +14454 +14455 +14456 +14457 +14458 +14459 +14460 +14461 +14462 +14463 +14464 +14465 +14466 +14467 +14468 +14469 +14470 +14471 +14472 +14473 +14474 +14475 +14476 +14477 +14478 +14479 +14480 +14481 +14482 +14483 +14484 +14485 +14486 +14487 +14488 +14489 +14490 +14491 +14492 +14493 +14494 +14495 +14496 +14497 +14498 +14499 +14500 +14501 +14502 +14503 +14504 +14505 +14506 +14507 +14508 +14509 +14510 +14511 +14512 +14513 +14514 +14515 +14516 +14517 +14518 +14519 +14520 +14521 +14522 +14523 +14524 +14525 +14526 +14527 +14528 +14529 +14530 +14531 +14532 +14533 +14534 +14535 +14536 +14537 +14538 +14539 +14540 +14541 +14542 +14543 +14544 +14545 +14546 +14547 +14548 +14549 +14550 +14551 +14552 +14553 +14554 +14555 +14556 +14557 +14558 +14559 +14560 +14561 +14562 +14563 +14564 +14565 +14566 +14567 +14568 +14569 +14570 +14571 +14572 +14573 +14574 +14575 +14576 +14577 +14578 +14579 +14580 +14581 +14582 +14583 +14584 +14585 +14586 +14587 +14588 +14589 +14590 +14591 +14592 +14593 +14594 +14595 +14596 +14597 +14598 +14599 +14600 +14601 +14602 +14603 +14604 +14605 +14606 +14607 +14608 +14609 +14610 +14611 +14612 +14613 +14614 +14615 +14616 +14617 +14618 +14619 +14620 +14621 +14622 +14623 +14624 +14625 +14626 +14627 +14628 +14629 +14630 +14631 +14632 +14633 +14634 +14635 +14636 +14637 +14638 +14639 +14640 +14641 +14642 +14643 +14644 +14645 +14646 +14647 +14648 +14649 +14650 +14651 +14652 +14653 +14654 +14655 +14656 +14657 +14658 +14659 +14660 +14661 +14662 +14663 +14664 +14665 +14666 +14667 +14668 +14669 +14670 +14671 +14672 +14673 +14674 +14675 +14676 +14677 +14678 +14679 +14680 +14681 +14682 +14683 +14684 +14685 +14686 +14687 +14688 +14689 +14690 +14691 +14692 +14693 +14694 +14695 +14696 +14697 +14698 +14699 +14700 +14701 +14702 +14703 +14704 +14705 +14706 +14707 +14708 +14709 +14710 +14711 +14712 +14713 +14714 +14715 +14716 +14717 +14718 +14719 +14720 +14721 +14722 +14723 +14724 +14725 +14726 +14727 +14728 +14729 +14730 +14731 +14732 +14733 +14734 +14735 +14736 +14737 +14738 +14739 +14740 +14741 +14742 +14743 +14744 +14745 +14746 +14747 +14748 +14749 +14750 +14751 +14752 +14753 +14754 +14755 +14756 +14757 +14758 +14759 +14760 +14761 +14762 +14763 +14764 +14765 +14766 +14767 +14768 +14769 +14770 +14771 +14772 +14773 +14774 +14775 +14776 +14777 +14778 +14779 +14780 +14781 +14782 +14783 +14784 +14785 +14786 +14787 +14788 +14789 +14790 +14791 +14792 +14793 +14794 +14795 +14796 +14797 +14798 +14799 +14800 +14801 +14802 +14803 +14804 +14805 +14806 +14807 +14808 +14809 +14810 +14811 +14812 +14813 +14814 +14815 +14816 +14817 +14818 +14819 +14820 +14821 +14822 +14823 +14824 +14825 +14826 +14827 +14828 +14829 +14830 +14831 +14832 +14833 +14834 +14835 +14836 +14837 +14838 +14839 +14840 +14841 +14842 +14843 +14844 +14845 +14846 +14847 +14848 +14849 +14850 +14851 +14852 +14853 +14854 +14855 +14856 +14857 +14858 +14859 +14860 +14861 +14862 +14863 +14864 +14865 +14866 +14867 +14868 +14869 +14870 +14871 +14872 +14873 +14874 +14875 +14876 +14877 +14878 +14879 +14880 +14881 +14882 +14883 +14884 +14885 +14886 +14887 +14888 +14889 +14890 +14891 +14892 +14893 +14894 +14895 +14896 +14897 +14898 +14899 +14900 +14901 +14902 +14903 +14904 +14905 +14906 +14907 +14908 +14909 +14910 +14911 +14912 +14913 +14914 +14915 +14916 +14917 +14918 +14919 +14920 +14921 +14922 +14923 +14924 +14925 +14926 +14927 +14928 +14929 +14930 +14931 +14932 +14933 +14934 +14935 +14936 +14937 +14938 +14939 +14940 +14941 +14942 +14943 +14944 +14945 +14946 +14947 +14948 +14949 +14950 +14951 +14952 +14953 +14954 +14955 +14956 +14957 +14958 +14959 +14960 +14961 +14962 +14963 +14964 +14965 +14966 +14967 +14968 +14969 +14970 +14971 +14972 +14973 +14974 +14975 +14976 +14977 +14978 +14979 +14980 +14981 +14982 +14983 +14984 +14985 +14986 +14987 +14988 +14989 +14990 +14991 +14992 +14993 +14994 +14995 +14996 +14997 +14998 +14999 +15000 +15001 +15002 +15003 +15004 +15005 +15006 +15007 +15008 +15009 +15010 +15011 +15012 +15013 +15014 +15015 +15016 +15017 +15018 +15019 +15020 +15021 +15022 +15023 +15024 +15025 +15026 +15027 +15028 +15029 +15030 +15031 +15032 +15033 +15034 +15035 +15036 +15037 +15038 +15039 +15040 +15041 +15042 +15043 +15044 +15045 +15046 +15047 +15048 +15049 +15050 +15051 +15052 +15053 +15054 +15055 +15056 +15057 +15058 +15059 +15060 +15061 +15062 +15063 +15064 +15065 +15066 +15067 +15068 +15069 +15070 +15071 +15072 +15073 +15074 +15075 +15076 +15077 +15078 +15079 +15080 +15081 +15082 +15083 +15084 +15085 +15086 +15087 +15088 +15089 +15090 +15091 +15092 +15093 +15094 +15095 +15096 +15097 +15098 +15099 +15100 +15101 +15102 +15103 +15104 +15105 +15106 +15107 +15108 +15109 +15110 +15111 +15112 +15113 +15114 +15115 +15116 +15117 +15118 +15119 +15120 +15121 +15122 +15123 +15124 +15125 +15126 +15127 +15128 +15129 +15130 +15131 +15132 +15133 +15134 +15135 +15136 +15137 +15138 +15139 +15140 +15141 +15142 +15143 +15144 +15145 +15146 +15147 +15148 +15149 +15150 +15151 +15152 +15153 +15154 +15155 +15156 +15157 +15158 +15159 +15160 +15161 +15162 +15163 +15164 +15165 +15166 +15167 +15168 +15169 +15170 +15171 +15172 +15173 +15174 +15175 +15176 +15177 +15178 +15179 +15180 +15181 +15182 +15183 +15184 +15185 +15186 +15187 +15188 +15189 +15190 +15191 +15192 +15193 +15194 +15195 +15196 +15197 +15198 +15199 +15200 +15201 +15202 +15203 +15204 +15205 +15206 +15207 +15208 +15209 +15210 +15211 +15212 +15213 +15214 +15215 +15216 +15217 +15218 +15219 +15220 +15221 +15222 +15223 +15224 +15225 +15226 +15227 +15228 +15229 +15230 +15231 +15232 +15233 +15234 +15235 +15236 +15237 +15238 +15239 +15240 +15241 +15242 +15243 +15244 +15245 +15246 +15247 +15248 +15249 +15250 +15251 +15252 +15253 +15254 +15255 +15256 +15257 +15258 +15259 +15260 +15261 +15262 +15263 +15264 +15265 +15266 +15267 +15268 +15269 +15270 +15271 +15272 +15273 +15274 +15275 +15276 +15277 +15278 +15279 +15280 +15281 +15282 +15283 +15284 +15285 +15286 +15287 +15288 +15289 +15290 +15291 +15292 +15293 +15294 +15295 +15296 +15297 +15298 +15299 +15300 +15301 +15302 +15303 +15304 +15305 +15306 +15307 +15308 +15309 +15310 +15311 +15312 +15313 +15314 +15315 +15316 +15317 +15318 +15319 +15320 +15321 +15322 +15323 +15324 +15325 +15326 +15327 +15328 +15329 +15330 +15331 +15332 +15333 +15334 +15335 +15336 +15337 +15338 +15339 +15340 +15341 +15342 +15343 +15344 +15345 +15346 +15347 +15348 +15349 +15350 +15351 +15352 +15353 +15354 +15355 +15356 +15357 +15358 +15359 +15360 +15361 +15362 +15363 +15364 +15365 +15366 +15367 +15368 +15369 +15370 +15371 +15372 +15373 +15374 +15375 +15376 +15377 +15378 +15379 +15380 +15381 +15382 +15383 +15384 +15385 +15386 +15387 +15388 +15389 +15390 +15391 +15392 +15393 +15394 +15395 +15396 +15397 +15398 +15399 +15400 +15401 +15402 +15403 +15404 +15405 +15406 +15407 +15408 +15409 +15410 +15411 +15412 +15413 +15414 +15415 +15416 +15417 +15418 +15419 +15420 +15421 +15422 +15423 +15424 +15425 +15426 +15427 +15428 +15429 +15430 +15431 +15432 +15433 +15434 +15435 +15436 +15437 +15438 +15439 +15440 +15441 +15442 +15443 +15444 +15445 +15446 +15447 +15448 +15449 +15450 +15451 +15452 +15453 +15454 +15455 +15456 +15457 +15458 +15459 +15460 +15461 +15462 +15463 +15464 +15465 +15466 +15467 +15468 +15469 +15470 +15471 +15472 +15473 +15474 +15475 +15476 +15477 +15478 +15479 +15480 +15481 +15482 +15483 +15484 +15485 +15486 +15487 +15488 +15489 +15490 +15491 +15492 +15493 +15494 +15495 +15496 +15497 +15498 +15499 +15500 +15501 +15502 +15503 +15504 +15505 +15506 +15507 +15508 +15509 +15510 +15511 +15512 +15513 +15514 +15515 +15516 +15517 +15518 +15519 +15520 +15521 +15522 +15523 +15524 +15525 +15526 +15527 +15528 +15529 +15530 +15531 +15532 +15533 +15534 +15535 +15536 +15537 +15538 +15539 +15540 +15541 +15542 +15543 +15544 +15545 +15546 +15547 +15548 +15549 +15550 +15551 +15552 +15553 +15554 +15555 +15556 +15557 +15558 +15559 +15560 +15561 +15562 +15563 +15564 +15565 +15566 +15567 +15568 +15569 +15570 +15571 +15572 +15573 +15574 +15575 +15576 +15577 +15578 +15579 +15580 +15581 +15582 +15583 +15584 +15585 +15586 +15587 +15588 +15589 +15590 +15591 +15592 +15593 +15594 +15595 +15596 +15597 +15598 +15599 +15600 +15601 +15602 +15603 +15604 +15605 +15606 +15607 +15608 +15609 +15610 +15611 +15612 +15613 +15614 +15615 +15616 +15617 +15618 +15619 +15620 +15621 +15622 +15623 +15624 +15625 +15626 +15627 +15628 +15629 +15630 +15631 +15632 +15633 +15634 +15635 +15636 +15637 +15638 +15639 +15640 +15641 +15642 +15643 +15644 +15645 +15646 +15647 +15648 +15649 +15650 +15651 +15652 +15653 +15654 +15655 +15656 +15657 +15658 +15659 +15660 +15661 +15662 +15663 +15664 +15665 +15666 +15667 +15668 +15669 +15670 +15671 +15672 +15673 +15674 +15675 +15676 +15677 +15678 +15679 +15680 +15681 +15682 +15683 +15684 +15685 +15686 +15687 +15688 +15689 +15690 +15691 +15692 +15693 +15694 +15695 +15696 +15697 +15698 +15699 +15700 +15701 +15702 +15703 +15704 +15705 +15706 +15707 +15708 +15709 +15710 +15711 +15712 +15713 +15714 +15715 +15716 +15717 +15718 +15719 +15720 +15721 +15722 +15723 +15724 +15725 +15726 +15727 +15728 +15729 +15730 +15731 +15732 +15733 +15734 +15735 +15736 +15737 +15738 +15739 +15740 +15741 +15742 +15743 +15744 +15745 +15746 +15747 +15748 +15749 +15750 +15751 +15752 +15753 +15754 +15755 +15756 +15757 +15758 +15759 +15760 +15761 +15762 +15763 +15764 +15765 +15766 +15767 +15768 +15769 +15770 +15771 +15772 +15773 +15774 +15775 +15776 +15777 +15778 +15779 +15780 +15781 +15782 +15783 +15784 +15785 +15786 +15787 +15788 +15789 +15790 +15791 +15792 +15793 +15794 +15795 +15796 +15797 +15798 +15799 +15800 +15801 +15802 +15803 +15804 +15805 +15806 +15807 +15808 +15809 +15810 +15811 +15812 +15813 +15814 +15815 +15816 +15817 +15818 +15819 +15820 +15821 +15822 +15823 +15824 +15825 +15826 +15827 +15828 +15829 +15830 +15831 +15832 +15833 +15834 +15835 +15836 +15837 +15838 +15839 +15840 +15841 +15842 +15843 +15844 +15845 +15846 +15847 +15848 +15849 +15850 +15851 +15852 +15853 +15854 +15855 +15856 +15857 +15858 +15859 +15860 +15861 +15862 +15863 +15864 +15865 +15866 +15867 +15868 +15869 +15870 +15871 +15872 +15873 +15874 +15875 +15876 +15877 +15878 +15879 +15880 +15881 +15882 +15883 +15884 +15885 +15886 +15887 +15888 +15889 +15890 +15891 +15892 +15893 +15894 +15895 +15896 +15897 +15898 +15899 +15900 +15901 +15902 +15903 +15904 +15905 +15906 +15907 +15908 +15909 +15910 +15911 +15912 +15913 +15914 +15915 +15916 +15917 +15918 +15919 +15920 +15921 +15922 +15923 +15924 +15925 +15926 +15927 +15928 +15929 +15930 +15931 +15932 +15933 +15934 +15935 +15936 +15937 +15938 +15939 +15940 +15941 +15942 +15943 +15944 +15945 +15946 +15947 +15948 +15949 +15950 +15951 +15952 +15953 +15954 +15955 +15956 +15957 +15958 +15959 +15960 +15961 +15962 +15963 +15964 +15965 +15966 +15967 +15968 +15969 +15970 +15971 +15972 +15973 +15974 +15975 +15976 +15977 +15978 +15979 +15980 +15981 +15982 +15983 +15984 +15985 +15986 +15987 +15988 +15989 +15990 +15991 +15992 +15993 +15994 +15995 +15996 +15997 +15998 +15999 +16000 +16001 +16002 +16003 +16004 +16005 +16006 +16007 +16008 +16009 +16010 +16011 +16012 +16013 +16014 +16015 +16016 +16017 +16018 +16019 +16020 +16021 +16022 +16023 +16024 +16025 +16026 +16027 +16028 +16029 +16030 +16031 +16032 +16033 +16034 +16035 +16036 +16037 +16038 +16039 +16040 +16041 +16042 +16043 +16044 +16045 +16046 +16047 +16048 +16049 +16050 +16051 +16052 +16053 +16054 +16055 +16056 +16057 +16058 +16059 +16060 +16061 +16062 +16063 +16064 +16065 +16066 +16067 +16068 +16069 +16070 +16071 +16072 +16073 +16074 +16075 +16076 +16077 +16078 +16079 +16080 +16081 +16082 +16083 +16084 +16085 +16086 +16087 +16088 +16089 +16090 +16091 +16092 +16093 +16094 +16095 +16096 +16097 +16098 +16099 +16100 +16101 +16102 +16103 +16104 +16105 +16106 +16107 +16108 +16109 +16110 +16111 +16112 +16113 +16114 +16115 +16116 +16117 +16118 +16119 +16120 +16121 +16122 +16123 +16124 +16125 +16126 +16127 +16128 +16129 +16130 +16131 +16132 +16133 +16134 +16135 +16136 +16137 +16138 +16139 +16140 +16141 +16142 +16143 +16144 +16145 +16146 +16147 +16148 +16149 +16150 +16151 +16152 +16153 +16154 +16155 +16156 +16157 +16158 +16159 +16160 +16161 +16162 +16163 +16164 +16165 +16166 +16167 +16168 +16169 +16170 +16171 +16172 +16173 +16174 +16175 +16176 +16177 +16178 +16179 +16180 +16181 +16182 +16183 +16184 +16185 +16186 +16187 +16188 +16189 +16190 +16191 +16192 +16193 +16194 +16195 +16196 +16197 +16198 +16199 +16200 +16201 +16202 +16203 +16204 +16205 +16206 +16207 +16208 +16209 +16210 +16211 +16212 +16213 +16214 +16215 +16216 +16217 +16218 +16219 +16220 +16221 +16222 +16223 +16224 +16225 +16226 +16227 +16228 +16229 +16230 +16231 +16232 +16233 +16234 +16235 +16236 +16237 +16238 +16239 +16240 +16241 +16242 +16243 +16244 +16245 +16246 +16247 +16248 +16249 +16250 +16251 +16252 +16253 +16254 +16255 +16256 +16257 +16258 +16259 +16260 +16261 +16262 +16263 +16264 +16265 +16266 +16267 +16268 +16269 +16270 +16271 +16272 +16273 +16274 +16275 +16276 +16277 +16278 +16279 +16280 +16281 +16282 +16283 +16284 +16285 +16286 +16287 +16288 +16289 +16290 +16291 +16292 +16293 +16294 +16295 +16296 +16297 +16298 +16299 +16300 +16301 +16302 +16303 +16304 +16305 +16306 +16307 +16308 +16309 +16310 +16311 +16312 +16313 +16314 +16315 +16316 +16317 +16318 +16319 +16320 +16321 +16322 +16323 +16324 +16325 +16326 +16327 +16328 +16329 +16330 +16331 +16332 +16333 +16334 +16335 +16336 +16337 +16338 +16339 +16340 +16341 +16342 +16343 +16344 +16345 +16346 +16347 +16348 +16349 +16350 +16351 +16352 +16353 +16354 +16355 +16356 +16357 +16358 +16359 +16360 +16361 +16362 +16363 +16364 +16365 +16366 +16367 +16368 +16369 +16370 +16371 +16372 +16373 +16374 +16375 +16376 +16377 +16378 +16379 +16380 +16381 +16382 +16383 +16384 +16385 +16386 +16387 +16388 +16389 +16390 +16391 +16392 +16393 +16394 +16395 +16396 +16397 +16398 +16399 +16400 +16401 +16402 +16403 +16404 +16405 +16406 +16407 +16408 +16409 +16410 +16411 +16412 +16413 +16414 +16415 +16416 +16417 +16418 +16419 +16420 +16421 +16422 +16423 +16424 +16425 +16426 +16427 +16428 +16429 +16430 +16431 +16432 +16433 +16434 +16435 +16436 +16437 +16438 +16439 +16440 +16441 +16442 +16443 +16444 +16445 +16446 +16447 +16448 +16449 +16450 +16451 +16452 +16453 +16454 +16455 +16456 +16457 +16458 +16459 +16460 +16461 +16462 +16463 +16464 +16465 +16466 +16467 +16468 +16469 +16470 +16471 +16472 +16473 +16474 +16475 +16476 +16477 +16478 +16479 +16480 +16481 +16482 +16483 +16484 +16485 +16486 +16487 +16488 +16489 +16490 +16491 +16492 +16493 +16494 +16495 +16496 +16497 +16498 +16499 +16500 +16501 +16502 +16503 +16504 +16505 +16506 +16507 +16508 +16509 +16510 +16511 +16512 +16513 +16514 +16515 +16516 +16517 +16518 +16519 +16520 +16521 +16522 +16523 +16524 +16525 +16526 +16527 +16528 +16529 +16530 +16531 +16532 +16533 +16534 +16535 +16536 +16537 +16538 +16539 +16540 +16541 +16542 +16543 +16544 +16545 +16546 +16547 +16548 +16549 +16550 +16551 +16552 +16553 +16554 +16555 +16556 +16557 +16558 +16559 +16560 +16561 +16562 +16563 +16564 +16565 +16566 +16567 +16568 +16569 +16570 +16571 +16572 +16573 +16574 +16575 +16576 +16577 +16578 +16579 +16580 +16581 +16582 +16583 +16584 +16585 +16586 +16587 +16588 +16589 +16590 +16591 +16592 +16593 +16594 +16595 +16596 +16597 +16598 +16599 +16600 +16601 +16602 +16603 +16604 +16605 +16606 +16607 +16608 +16609 +16610 +16611 +16612 +16613 +16614 +16615 +16616 +16617 +16618 +16619 +16620 +16621 +16622 +16623 +16624 +16625 +16626 +16627 +16628 +16629 +16630 +16631 +16632 +16633 +16634 +16635 +16636 +16637 +16638 +16639 +16640 +16641 +16642 +16643 +16644 +16645 +16646 +16647 +16648 +16649 +16650 +16651 +16652 +16653 +16654 +16655 +16656 +16657 +16658 +16659 +16660 +16661 +16662 +16663 +16664 +16665 +16666 +16667 +16668 +16669 +16670 +16671 +16672 +16673 +16674 +16675 +16676 +16677 +16678 +16679 +16680 +16681 +16682 +16683 +16684 +16685 +16686 +16687 +16688 +16689 +16690 +16691 +16692 +16693 +16694 +16695 +16696 +16697 +16698 +16699 +16700 +16701 +16702 +16703 +16704 +16705 +16706 +16707 +16708 +16709 +16710 +16711 +16712 +16713 +16714 +16715 +16716 +16717 +16718 +16719 +16720 +16721 +16722 +16723 +16724 +16725 +16726 +16727 +16728 +16729 +16730 +16731 +16732 +16733 +16734 +16735 +16736 +16737 +16738 +16739 +16740 +16741 +16742 +16743 +16744 +16745 +16746 +16747 +16748 +16749 +16750 +16751 +16752 +16753 +16754 +16755 +16756 +16757 +16758 +16759 +16760 +16761 +16762 +16763 +16764 +16765 +16766 +16767 +16768 +16769 +16770 +16771 +16772 +16773 +16774 +16775 +16776 +16777 +16778 +16779 +16780 +16781 +16782 +16783 +16784 +16785 +16786 +16787 +16788 +16789 +16790 +16791 +16792 +16793 +16794 +16795 +16796 +16797 +16798 +16799 +16800 +16801 +16802 +16803 +16804 +16805 +16806 +16807 +16808 +16809 +16810 +16811 +16812 +16813 +16814 +16815 +16816 +16817 +16818 +16819 +16820 +16821 +16822 +16823 +16824 +16825 +16826 +16827 +16828 +16829 +16830 +16831 +16832 +16833 +16834 +16835 +16836 +16837 +16838 +16839 +16840 +16841 +16842 +16843 +16844 +16845 +16846 +16847 +16848 +16849 +16850 +16851 +16852 +16853 +16854 +16855 +16856 +16857 +16858 +16859 +16860 +16861 +16862 +16863 +16864 +16865 +16866 +16867 +16868 +16869 +16870 +16871 +16872 +16873 +16874 +16875 +16876 +16877 +16878 +16879 +16880 +16881 +16882 +16883 +16884 +16885 +16886 +16887 +16888 +16889 +16890 +16891 +16892 +16893 +16894 +16895 +16896 +16897 +16898 +16899 +16900 +16901 +16902 +16903 +16904 +16905 +16906 +16907 +16908 +16909 +16910 +16911 +16912 +16913 +16914 +16915 +16916 +16917 +16918 +16919 +16920 +16921 +16922 +16923 +16924 +16925 +16926 +16927 +16928 +16929 +16930 +16931 +16932 +16933 +16934 +16935 +16936 +16937 +16938 +16939 +16940 +16941 +16942 +16943 +16944 +16945 +16946 +16947 +16948 +16949 +16950 +16951 +16952 +16953 +16954 +16955 +16956 +16957 +16958 +16959 +16960 +16961 +16962 +16963 +16964 +16965 +16966 +16967 +16968 +16969 +16970 +16971 +16972 +16973 +16974 +16975 +16976 +16977 +16978 +16979 +16980 +16981 +16982 +16983 +16984 +16985 +16986 +16987 +16988 +16989 +16990 +16991 +16992 +16993 +16994 +16995 +16996 +16997 +16998 +16999 +17000 +17001 +17002 +17003 +17004 +17005 +17006 +17007 +17008 +17009 +17010 +17011 +17012 +17013 +17014 +17015 +17016 +17017 +17018 +17019 +17020 +17021 +17022 +17023 +17024 +17025 +17026 +17027 +17028 +17029 +17030 +17031 +17032 +17033 +17034 +17035 +17036 +17037 +17038 +17039 +17040 +17041 +17042 +17043 +17044 +17045 +17046 +17047 +17048 +17049 +17050 +17051 +17052 +17053 +17054 +17055 +17056 +17057 +17058 +17059 +17060 +17061 +17062 +17063 +17064 +17065 +17066 +17067 +17068 +17069 +17070 +17071 +17072 +17073 +17074 +17075 +17076 +17077 +17078 +17079 +17080 +17081 +17082 +17083 +17084 +17085 +17086 +17087 +17088 +17089 +17090 +17091 +17092 +17093 +17094 +17095 +17096 +17097 +17098 +17099 +17100 +17101 +17102 +17103 +17104 +17105 +17106 +17107 +17108 +17109 +17110 +17111 +17112 +17113 +17114 +17115 +17116 +17117 +17118 +17119 +17120 +17121 +17122 +17123 +17124 +17125 +17126 +17127 +17128 +17129 +17130 +17131 +17132 +17133 +17134 +17135 +17136 +17137 +17138 +17139 +17140 +17141 +17142 +17143 +17144 +17145 +17146 +17147 +17148 +17149 +17150 +17151 +17152 +17153 +17154 +17155 +17156 +17157 +17158 +17159 +17160 +17161 +17162 +17163 +17164 +17165 +17166 +17167 +17168 +17169 +17170 +17171 +17172 +17173 +17174 +17175 +17176 +17177 +17178 +17179 +17180 +17181 +17182 +17183 +17184 +17185 +17186 +17187 +17188 +17189 +17190 +17191 +17192 +17193 +17194 +17195 +17196 +17197 +17198 +17199 +17200 +17201 +17202 +17203 +17204 +17205 +17206 +17207 +17208 +17209 +17210 +17211 +17212 +17213 +17214 +17215 +17216 +17217 +17218 +17219 +17220 +17221 +17222 +17223 +17224 +17225 +17226 +17227 +17228 +17229 +17230 +17231 +17232 +17233 +17234 +17235 +17236 +17237 +17238 +17239 +17240 +17241 +17242 +17243 +17244 +17245 +17246 +17247 +17248 +17249 +17250 +17251 +17252 +17253 +17254 +17255 +17256 +17257 +17258 +17259 +17260 +17261 +17262 +17263 +17264 +17265 +17266 +17267 +17268 +17269 +17270 +17271 +17272 +17273 +17274 +17275 +17276 +17277 +17278 +17279 +17280 +17281 +17282 +17283 +17284 +17285 +17286 +17287 +17288 +17289 +17290 +17291 +17292 +17293 +17294 +17295 +17296 +17297 +17298 +17299 +17300 +17301 +17302 +17303 +17304 +17305 +17306 +17307 +17308 +17309 +17310 +17311 +17312 +17313 +17314 +17315 +17316 +17317 +17318 +17319 +17320 +17321 +17322 +17323 +17324 +17325 +17326 +17327 +17328 +17329 +17330 +17331 +17332 +17333 +17334 +17335 +17336 +17337 +17338 +17339 +17340 +17341 +17342 +17343 +17344 +17345 +17346 +17347 +17348 +17349 +17350 +17351 +17352 +17353 +17354 +17355 +17356 +17357 +17358 +17359 +17360 +17361 +17362 +17363 +17364 +17365 +17366 +17367 +17368 +17369 +17370 +17371 +17372 +17373 +17374 +17375 +17376 +17377 +17378 +17379 +17380 +17381 +17382 +17383 +17384 +17385 +17386 +17387 +17388 +17389 +17390 +17391 +17392 +17393 +17394 +17395 +17396 +17397 +17398 +17399 +17400 +17401 +17402 +17403 +17404 +17405 +17406 +17407 +17408 +17409 +17410 +17411 +17412 +17413 +17414 +17415 +17416 +17417 +17418 +17419 +17420 +17421 +17422 +17423 +17424 +17425 +17426 +17427 +17428 +17429 +17430 +17431 +17432 +17433 +17434 +17435 +17436 +17437 +17438 +17439 +17440 +17441 +17442 +17443 +17444 +17445 +17446 +17447 +17448 +17449 +17450 +17451 +17452 +17453 +17454 +17455 +17456 +17457 +17458 +17459 +17460 +17461 +17462 +17463 +17464 +17465 +17466 +17467 +17468 +17469 +17470 +17471 +17472 +17473 +17474 +17475 +17476 +17477 +17478 +17479 +17480 +17481 +17482 +17483 +17484 +17485 +17486 +17487 +17488 +17489 +17490 +17491 +17492 +17493 +17494 +17495 +17496 +17497 +17498 +17499 +17500 +17501 +17502 +17503 +17504 +17505 +17506 +17507 +17508 +17509 +17510 +17511 +17512 +17513 +17514 +17515 +17516 +17517 +17518 +17519 +17520 +17521 +17522 +17523 +17524 +17525 +17526 +17527 +17528 +17529 +17530 +17531 +17532 +17533 +17534 +17535 +17536 +17537 +17538 +17539 +17540 +17541 +17542 +17543 +17544 +17545 +17546 +17547 +17548 +17549 +17550 +17551 +17552 +17553 +17554 +17555 +17556 +17557 +17558 +17559 +17560 +17561 +17562 +17563 +17564 +17565 +17566 +17567 +17568 +17569 +17570 +17571 +17572 +17573 +17574 +17575 +17576 +17577 +17578 +17579 +17580 +17581 +17582 +17583 +17584 +17585 +17586 +17587 +17588 +17589 +17590 +17591 +17592 +17593 +17594 +17595 +17596 +17597 +17598 +17599 +17600 +17601 +17602 +17603 +17604 +17605 +17606 +17607 +17608 +17609 +17610 +17611 +17612 +17613 +17614 +17615 +17616 +17617 +17618 +17619 +17620 +17621 +17622 +17623 +17624 +17625 +17626 +17627 +17628 +17629 +17630 +17631 +17632 +17633 +17634 +17635 +17636 +17637 +17638 +17639 +17640 +17641 +17642 +17643 +17644 +17645 +17646 +17647 +17648 +17649 +17650 +17651 +17652 +17653 +17654 +17655 +17656 +17657 +17658 +17659 +17660 +17661 +17662 +17663 +17664 +17665 +17666 +17667 +17668 +17669 +17670 +17671 +17672 +17673 +17674 +17675 +17676 +17677 +17678 +17679 +17680 +17681 +17682 +17683 +17684 +17685 +17686 +17687 +17688 +17689 +17690 +17691 +17692 +17693 +17694 +17695 +17696 +17697 +17698 +17699 +17700 +17701 +17702 +17703 +17704 +17705 +17706 +17707 +17708 +17709 +17710 +17711 +17712 +17713 +17714 +17715 +17716 +17717 +17718 +17719 +17720 +17721 +17722 +17723 +17724 +17725 +17726 +17727 +17728 +17729 +17730 +17731 +17732 +17733 +17734 +17735 +17736 +17737 +17738 +17739 +17740 +17741 +17742 +17743 +17744 +17745 +17746 +17747 +17748 +17749 +17750 +17751 +17752 +17753 +17754 +17755 +17756 +17757 +17758 +17759 +17760 +17761 +17762 +17763 +17764 +17765 +17766 +17767 +17768 +17769 +17770 +17771 +17772 +17773 +17774 +17775 +17776 +17777 +17778 +17779 +17780 +17781 +17782 +17783 +17784 +17785 +17786 +17787 +17788 +17789 +17790 +17791 +17792 +17793 +17794 +17795 +17796 +17797 +17798 +17799 +17800 +17801 +17802 +17803 +17804 +17805 +17806 +17807 +17808 +17809 +17810 +17811 +17812 +17813 +17814 +17815 +17816 +17817 +17818 +17819 +17820 +17821 +17822 +17823 +17824 +17825 +17826 +17827 +17828 +17829 +17830 +17831 +17832 +17833 +17834 +17835 +17836 +17837 +17838 +17839 +17840 +17841 +17842 +17843 +17844 +17845 +17846 +17847 +17848 +17849 +17850 +17851 +17852 +17853 +17854 +17855 +17856 +17857 +17858 +17859 +17860 +17861 +17862 +17863 +17864 +17865 +17866 +17867 +17868 +17869 +17870 +17871 +17872 +17873 +17874 +17875 +17876 +17877 +17878 +17879 +17880 +17881 +17882 +17883 +17884 +17885 +17886 +17887 +17888 +17889 +17890 +17891 +17892 +17893 +17894 +17895 +17896 +17897 +17898 +17899 +17900 +17901 +17902 +17903 +17904 +17905 +17906 +17907 +17908 +17909 +17910 +17911 +17912 +17913 +17914 +17915 +17916 +17917 +17918 +17919 +17920 +17921 +17922 +17923 +17924 +17925 +17926 +17927 +17928 +17929 +17930 +17931 +17932 +17933 +17934 +17935 +17936 +17937 +17938 +17939 +17940 +17941 +17942 +17943 +17944 +17945 +17946 +17947 +17948 +17949 +17950 +17951 +17952 +17953 +17954 +17955 +17956 +17957 +17958 +17959 +17960 +17961 +17962 +17963 +17964 +17965 +17966 +17967 +17968 +17969 +17970 +17971 +17972 +17973 +17974 +17975 +17976 +17977 +17978 +17979 +17980 +17981 +17982 +17983 +17984 +17985 +17986 +17987 +17988 +17989 +17990 +17991 +17992 +17993 +17994 +17995 +17996 +17997 +17998 +17999 +18000 +18001 +18002 +18003 +18004 +18005 +18006 +18007 +18008 +18009 +18010 +18011 +18012 +18013 +18014 +18015 +18016 +18017 +18018 +18019 +18020 +18021 +18022 +18023 +18024 +18025 +18026 +18027 +18028 +18029 +18030 +18031 +18032 +18033 +18034 +18035 +18036 +18037 +18038 +18039 +18040 +18041 +18042 +18043 +18044 +18045 +18046 +18047 +18048 +18049 +18050 +18051 +18052 +18053 +18054 +18055 +18056 +18057 +18058 +18059 +18060 +18061 +18062 +18063 +18064 +18065 +18066 +18067 +18068 +18069 +18070 +18071 +18072 +18073 +18074 +18075 +18076 +18077 +18078 +18079 +18080 +18081 +18082 +18083 +18084 +18085 +18086 +18087 +18088 +18089 +18090 +18091 +18092 +18093 +18094 +18095 +18096 +18097 +18098 +18099 +18100 +18101 +18102 +18103 +18104 +18105 +18106 +18107 +18108 +18109 +18110 +18111 +18112 +18113 +18114 +18115 +18116 +18117 +18118 +18119 +18120 +18121 +18122 +18123 +18124 +18125 +18126 +18127 +18128 +18129 +18130 +18131 +18132 +18133 +18134 +18135 +18136 +18137 +18138 +18139 +18140 +18141 +18142 +18143 +18144 +18145 +18146 +18147 +18148 +18149 +18150 +18151 +18152 +18153 +18154 +18155 +18156 +18157 +18158 +18159 +18160 +18161 +18162 +18163 +18164 +18165 +18166 +18167 +18168 +18169 +18170 +18171 +18172 +18173 +18174 +18175 +18176 +18177 +18178 +18179 +18180 +18181 +18182 +18183 +18184 +18185 +18186 +18187 +18188 +18189 +18190 +18191 +18192 +18193 +18194 +18195 +18196 +18197 +18198 +18199 +18200 +18201 +18202 +18203 +18204 +18205 +18206 +18207 +18208 +18209 +18210 +18211 +18212 +18213 +18214 +18215 +18216 +18217 +18218 +18219 +18220 +18221 +18222 +18223 +18224 +18225 +18226 +18227 +18228 +18229 +18230 +18231 +18232 +18233 +18234 +18235 +18236 +18237 +18238 +18239 +18240 +18241 +18242 +18243 +18244 +18245 +18246 +18247 +18248 +18249 +18250 +18251 +18252 +18253 +18254 +18255 +18256 +18257 +18258 +18259 +18260 +18261 +18262 +18263 +18264 +18265 +18266 +18267 +18268 +18269 +18270 +18271 +18272 +18273 +18274 +18275 +18276 +18277 +18278 +18279 +18280 +18281 +18282 +18283 +18284 +18285 +18286 +18287 +18288 +18289 +18290 +18291 +18292 +18293 +18294 +18295 +18296 +18297 +18298 +18299 +18300 +18301 +18302 +18303 +18304 +18305 +18306 +18307 +18308 +18309 +18310 +18311 +18312 +18313 +18314 +18315 +18316 +18317 +18318 +18319 +18320 +18321 +18322 +18323 +18324 +18325 +18326 +18327 +18328 +18329 +18330 +18331 +18332 +18333 +18334 +18335 +18336 +18337 +18338 +18339 +18340 +18341 +18342 +18343 +18344 +18345 +18346 +18347 +18348 +18349 +18350 +18351 +18352 +18353 +18354 +18355 +18356 +18357 +18358 +18359 +18360 +18361 +18362 +18363 +18364 +18365 +18366 +18367 +18368 +18369 +18370 +18371 +18372 +18373 +18374 +18375 +18376 +18377 +18378 +18379 +18380 +18381 +18382 +18383 +18384 +18385 +18386 +18387 +18388 +18389 +18390 +18391 +18392 +18393 +18394 +18395 +18396 +18397 +18398 +18399 +18400 +18401 +18402 +18403 +18404 +18405 +18406 +18407 +18408 +18409 +18410 +18411 +18412 +18413 +18414 +18415 +18416 +18417 +18418 +18419 +18420 +18421 +18422 +18423 +18424 +18425 +18426 +18427 +18428 +18429 +18430 +18431 +18432 +18433 +18434 +18435 +18436 +18437 +18438 +18439 +18440 +18441 +18442 +18443 +18444 +18445 +18446 +18447 +18448 +18449 +18450 +18451 +18452 +18453 +18454 +18455 +18456 +18457 +18458 +18459 +18460 +18461 +18462 +18463 +18464 +18465 +18466 +18467 +18468 +18469 +18470 +18471 +18472 +18473 +18474 +18475 +18476 +18477 +18478 +18479 +18480 +18481 +18482 +18483 +18484 +18485 +18486 +18487 +18488 +18489 +18490 +18491 +18492 +18493 +18494 +18495 +18496 +18497 +18498 +18499 +18500 +18501 +18502 +18503 +18504 +18505 +18506 +18507 +18508 +18509 +18510 +18511 +18512 +18513 +18514 +18515 +18516 +18517 +18518 +18519 +18520 +18521 +18522 +18523 +18524 +18525 +18526 +18527 +18528 +18529 +18530 +18531 +18532 +18533 +18534 +18535 +18536 +18537 +18538 +18539 +18540 +18541 +18542 +18543 +18544 +18545 +18546 +18547 +18548 +18549 +18550 +18551 +18552 +18553 +18554 +18555 +18556 +18557 +18558 +18559 +18560 +18561 +18562 +18563 +18564 +18565 +18566 +18567 +18568 +18569 +18570 +18571 +18572 +18573 +18574 +18575 +18576 +18577 +18578 +18579 +18580 +18581 +18582 +18583 +18584 +18585 +18586 +18587 +18588 +18589 +18590 +18591 +18592 +18593 +18594 +18595 +18596 +18597 +18598 +18599 +18600 +18601 +18602 +18603 +18604 +18605 +18606 +18607 +18608 +18609 +18610 +18611 +18612 +18613 +18614 +18615 +18616 +18617 +18618 +18619 +18620 +18621 +18622 +18623 +18624 +18625 +18626 +18627 +18628 +18629 +18630 +18631 +18632 +18633 +18634 +18635 +18636 +18637 +18638 +18639 +18640 +18641 +18642 +18643 +18644 +18645 +18646 +18647 +18648 +18649 +18650 +18651 +18652 +18653 +18654 +18655 +18656 +18657 +18658 +18659 +18660 +18661 +18662 +18663 +18664 +18665 +18666 +18667 +18668 +18669 +18670 +18671 +18672 +18673 +18674 +18675 +18676 +18677 +18678 +18679 +18680 +18681 +18682 +18683 +18684 +18685 +18686 +18687 +18688 +18689 +18690 +18691 +18692 +18693 +18694 +18695 +18696 +18697 +18698 +18699 +18700 +18701 +18702 +18703 +18704 +18705 +18706 +18707 +18708 +18709 +18710 +18711 +18712 +18713 +18714 +18715 +18716 +18717 +18718 +18719 +18720 +18721 +18722 +18723 +18724 +18725 +18726 +18727 +18728 +18729 +18730 +18731 +18732 +18733 +18734 +18735 +18736 +18737 +18738 +18739 +18740 +18741 +18742 +18743 +18744 +18745 +18746 +18747 +18748 +18749 +18750 +18751 +18752 +18753 +18754 +18755 +18756 +18757 +18758 +18759 +18760 +18761 +18762 +18763 +18764 +18765 +18766 +18767 +18768 +18769 +18770 +18771 +18772 +18773 +18774 +18775 +18776 +18777 +18778 +18779 +18780 +18781 +18782 +18783 +18784 +18785 +18786 +18787 +18788 +18789 +18790 +18791 +18792 +18793 +18794 +18795 +18796 +18797 +18798 +18799 +18800 +18801 +18802 +18803 +18804 +18805 +18806 +18807 +18808 +18809 +18810 +18811 +18812 +18813 +18814 +18815 +18816 +18817 +18818 +18819 +18820 +18821 +18822 +18823 +18824 +18825 +18826 +18827 +18828 +18829 +18830 +18831 +18832 +18833 +18834 +18835 +18836 +18837 +18838 +18839 +18840 +18841 +18842 +18843 +18844 +18845 +18846 +18847 +18848 +18849 +18850 +18851 +18852 +18853 +18854 +18855 +18856 +18857 +18858 +18859 +18860 +18861 +18862 +18863 +18864 +18865 +18866 +18867 +18868 +18869 +18870 +18871 +18872 +18873 +18874 +18875 +18876 +18877 +18878 +18879 +18880 +18881 +18882 +18883 +18884 +18885 +18886 +18887 +18888 +18889 +18890 +18891 +18892 +18893 +18894 +18895 +18896 +18897 +18898 +18899 +18900 +18901 +18902 +18903 +18904 +18905 +18906 +18907 +18908 +18909 +18910 +18911 +18912 +18913 +18914 +18915 +18916 +18917 +18918 +18919 +18920 +18921 +18922 +18923 +18924 +18925 +18926 +18927 +18928 +18929 +18930 +18931 +18932 +18933 +18934 +18935 +18936 +18937 +18938 +18939 +18940 +18941 +18942 +18943 +18944 +18945 +18946 +18947 +18948 +18949 +18950 +18951 +18952 +18953 +18954 +18955 +18956 +18957 +18958 +18959 +18960 +18961 +18962 +18963 +18964 +18965 +18966 +18967 +18968 +18969 +18970 +18971 +18972 +18973 +18974 +18975 +18976 +18977 +18978 +18979 +18980 +18981 +18982 +18983 +18984 +18985 +18986 +18987 +18988 +18989 +18990 +18991 +18992 +18993 +18994 +18995 +18996 +18997 +18998 +18999 +19000 +19001 +19002 +19003 +19004 +19005 +19006 +19007 +19008 +19009 +19010 +19011 +19012 +19013 +19014 +19015 +19016 +19017 +19018 +19019 +19020 +19021 +19022 +19023 +19024 +19025 +19026 +19027 +19028 +19029 +19030 +19031 +19032 +19033 +19034 +19035 +19036 +19037 +19038 +19039 +19040 +19041 +19042 +19043 +19044 +19045 +19046 +19047 +19048 +19049 +19050 +19051 +19052 +19053 +19054 +19055 +19056 +19057 +19058 +19059 +19060 +19061 +19062 +19063 +19064 +19065 +19066 +19067 +19068 +19069 +19070 +19071 +19072 +19073 +19074 +19075 +19076 +19077 +19078 +19079 +19080 +19081 +19082 +19083 +19084 +19085 +19086 +19087 +19088 +19089 +19090 +19091 +19092 +19093 +19094 +19095 +19096 +19097 +19098 +19099 +19100 +19101 +19102 +19103 +19104 +19105 +19106 +19107 +19108 +19109 +19110 +19111 +19112 +19113 +19114 +19115 +19116 +19117 +19118 +19119 +19120 +19121 +19122 +19123 +19124 +19125 +19126 +19127 +19128 +19129 +19130 +19131 +19132 +19133 +19134 +19135 +19136 +19137 +19138 +19139 +19140 +19141 +19142 +19143 +19144 +19145 +19146 +19147 +19148 +19149 +19150 +19151 +19152 +19153 +19154 +19155 +19156 +19157 +19158 +19159 +19160 +19161 +19162 +19163 +19164 +19165 +19166 +19167 +19168 +19169 +19170 +19171 +19172 +19173 +19174 +19175 +19176 +19177 +19178 +19179 +19180 +19181 +19182 +19183 +19184 +19185 +19186 +19187 +19188 +19189 +19190 +19191 +19192 +19193 +19194 +19195 +19196 +19197 +19198 +19199 +19200 +19201 +19202 +19203 +19204 +19205 +19206 +19207 +19208 +19209 +19210 +19211 +19212 +19213 +19214 +19215 +19216 +19217 +19218 +19219 +19220 +19221 +19222 +19223 +19224 +19225 +19226 +19227 +19228 +19229 +19230 +19231 +19232 +19233 +19234 +19235 +19236 +19237 +19238 +19239 +19240 +19241 +19242 +19243 +19244 +19245 +19246 +19247 +19248 +19249 +19250 +19251 +19252 +19253 +19254 +19255 +19256 +19257 +19258 +19259 +19260 +19261 +19262 +19263 +19264 +19265 +19266 +19267 +19268 +19269 +19270 +19271 +19272 +19273 +19274 +19275 +19276 +19277 +19278 +19279 +19280 +19281 +19282 +19283 +19284 +19285 +19286 +19287 +19288 +19289 +19290 +19291 +19292 +19293 +19294 +19295 +19296 +19297 +19298 +19299 +19300 +19301 +19302 +19303 +19304 +19305 +19306 +19307 +19308 +19309 +19310 +19311 +19312 +19313 +19314 +19315 +19316 +19317 +19318 +19319 +19320 +19321 +19322 +19323 +19324 +19325 +19326 +19327 +19328 +19329 +19330 +19331 +19332 +19333 +19334 +19335 +19336 +19337 +19338 +19339 +19340 +19341 +19342 +19343 +19344 +19345 +19346 +19347 +19348 +19349 +19350 +19351 +19352 +19353 +19354 +19355 +19356 +19357 +19358 +19359 +19360 +19361 +19362 +19363 +19364 +19365 +19366 +19367 +19368 +19369 +19370 +19371 +19372 +19373 +19374 +19375 +19376 +19377 +19378 +19379 +19380 +19381 +19382 +19383 +19384 +19385 +19386 +19387 +19388 +19389 +19390 +19391 +19392 +19393 +19394 +19395 +19396 +19397 +19398 +19399 +19400 +19401 +19402 +19403 +19404 +19405 +19406 +19407 +19408 +19409 +19410 +19411 +19412 +19413 +19414 +19415 +19416 +19417 +19418 +19419 +19420 +19421 +19422 +19423 +19424 +19425 +19426 +19427 +19428 +19429 +19430 +19431 +19432 +19433 +19434 +19435 +19436 +19437 +19438 +19439 +19440 +19441 +19442 +19443 +19444 +19445 +19446 +19447 +19448 +19449 +19450 +19451 +19452 +19453 +19454 +19455 +19456 +19457 +19458 +19459 +19460 +19461 +19462 +19463 +19464 +19465 +19466 +19467 +19468 +19469 +19470 +19471 +19472 +19473 +19474 +19475 +19476 +19477 +19478 +19479 +19480 +19481 +19482 +19483 +19484 +19485 +19486 +19487 +19488 +19489 +19490 +19491 +19492 +19493 +19494 +19495 +19496 +19497 +19498 +19499 +19500 +19501 +19502 +19503 +19504 +19505 +19506 +19507 +19508 +19509 +19510 +19511 +19512 +19513 +19514 +19515 +19516 +19517 +19518 +19519 +19520 +19521 +19522 +19523 +19524 +19525 +19526 +19527 +19528 +19529 +19530 +19531 +19532 +19533 +19534 +19535 +19536 +19537 +19538 +19539 +19540 +19541 +19542 +19543 +19544 +19545 +19546 +19547 +19548 +19549 +19550 +19551 +19552 +19553 +19554 +19555 +19556 +19557 +19558 +19559 +19560 +19561 +19562 +19563 +19564 +19565 +19566 +19567 +19568 +19569 +19570 +19571 +19572 +19573 +19574 +19575 +19576 +19577 +19578 +19579 +19580 +19581 +19582 +19583 +19584 +19585 +19586 +19587 +19588 +19589 +19590 +19591 +19592 +19593 +19594 +19595 +19596 +19597 +19598 +19599 +19600 +19601 +19602 +19603 +19604 +19605 +19606 +19607 +19608 +19609 +19610 +19611 +19612 +19613 +19614 +19615 +19616 +19617 +19618 +19619 +19620 +19621 +19622 +19623 +19624 +19625 +19626 +19627 +19628 +19629 +19630 +19631 +19632 +19633 +19634 +19635 +19636 +19637 +19638 +19639 +19640 +19641 +19642 +19643 +19644 +19645 +19646 +19647 +19648 +19649 +19650 +19651 +19652 +19653 +19654 +19655 +19656 +19657 +19658 +19659 +19660 +19661 +19662 +19663 +19664 +19665 +19666 +19667 +19668 +19669 +19670 +19671 +19672 +19673 +19674 +19675 +19676 +19677 +19678 +19679 +19680 +19681 +19682 +19683 +19684 +19685 +19686 +19687 +19688 +19689 +19690 +19691 +19692 +19693 +19694 +19695 +19696 +19697 +19698 +19699 +19700 +19701 +19702 +19703 +19704 +19705 +19706 +19707 +19708 +19709 +19710 +19711 +19712 +19713 +19714 +19715 +19716 +19717 +19718 +19719 +19720 +19721 +19722 +19723 +19724 +19725 +19726 +19727 +19728 +19729 +19730 +19731 +19732 +19733 +19734 +19735 +19736 +19737 +19738 +19739 +19740 +19741 +19742 +19743 +19744 +19745 +19746 +19747 +19748 +19749 +19750 +19751 +19752 +19753 +19754 +19755 +19756 +19757 +19758 +19759 +19760 +19761 +19762 +19763 +19764 +19765 +19766 +19767 +19768 +19769 +19770 +19771 +19772 +19773 +19774 +19775 +19776 +19777 +19778 +19779 +19780 +19781 +19782 +19783 +19784 +19785 +19786 +19787 +19788 +19789 +19790 +19791 +19792 +19793 +19794 +19795 +19796 +19797 +19798 +19799 +19800 +19801 +19802 +19803 +19804 +19805 +19806 +19807 +19808 +19809 +19810 +19811 +19812 +19813 +19814 +19815 +19816 +19817 +19818 +19819 +19820 +19821 +19822 +19823 +19824 +19825 +19826 +19827 +19828 +19829 +19830 +19831 +19832 +19833 +19834 +19835 +19836 +19837 +19838 +19839 +19840 +19841 +19842 +19843 +19844 +19845 +19846 +19847 +19848 +19849 +19850 +19851 +19852 +19853 +19854 +19855 +19856 +19857 +19858 +19859 +19860 +19861 +19862 +19863 +19864 +19865 +19866 +19867 +19868 +19869 +19870 +19871 +19872 +19873 +19874 +19875 +19876 +19877 +19878 +19879 +19880 +19881 +19882 +19883 +19884 +19885 +19886 +19887 +19888 +19889 +19890 +19891 +19892 +19893 +19894 +19895 +19896 +19897 +19898 +19899 +19900 +19901 +19902 +19903 +19904 +19905 +19906 +19907 +19908 +19909 +19910 +19911 +19912 +19913 +19914 +19915 +19916 +19917 +19918 +19919 +19920 +19921 +19922 +19923 +19924 +19925 +19926 +19927 +19928 +19929 +19930 +19931 +19932 +19933 +19934 +19935 +19936 +19937 +19938 +19939 +19940 +19941 +19942 +19943 +19944 +19945 +19946 +19947 +19948 +19949 +19950 +19951 +19952 +19953 +19954 +19955 +19956 +19957 +19958 +19959 +19960 +19961 +19962 +19963 +19964 +19965 +19966 +19967 +19968 +19969 +19970 +19971 +19972 +19973 +19974 +19975 +19976 +19977 +19978 +19979 +19980 +19981 +19982 +19983 +19984 +19985 +19986 +19987 +19988 +19989 +19990 +19991 +19992 +19993 +19994 +19995 +19996 +19997 +19998 +19999 +20000 diff --git a/tests/fixtures/sort/ext_sort.txt b/tests/fixtures/sort/ext_sort.txt new file mode 100644 index 000000000..a409d67e1 --- /dev/null +++ b/tests/fixtures/sort/ext_sort.txt @@ -0,0 +1,20000 @@ +9155 +10575 +10442 +15874 +17013 +12130 +15558 +18263 +6574 +8957 +9851 +16606 +12331 +9865 +13795 +270 +6590 +11141 +4620 +5945 +10904 +8652 +8442 +8907 +1935 +13100 +3961 +7538 +4159 +11986 +4394 +9321 +15560 +5264 +5121 +11532 +6980 +2807 +19760 +8032 +5158 +13698 +4458 +9106 +3773 +1625 +9914 +8287 +5155 +14326 +18137 +19522 +9270 +6153 +1920 +12517 +13259 +17618 +9930 +3630 +15924 +4540 +263 +14212 +15620 +11328 +8704 +17848 +1614 +12587 +17970 +4542 +11976 +12885 +8743 +16323 +14582 +12101 +12472 +12620 +10713 +5148 +7522 +2417 +8602 +7860 +19596 +2892 +13359 +7731 +3707 +4628 +4710 +5642 +1610 +4784 +10128 +16341 +14168 +5829 +17901 +9447 +1041 +15193 +15260 +11224 +11723 +13368 +14011 +12200 +2001 +18479 +3965 +16642 +16680 +2384 +7557 +5539 +4305 +14588 +17386 +1359 +17721 +1142 +7287 +9946 +13139 +15022 +17237 +14454 +14358 +11297 +12485 +857 +19282 +117 +19179 +16040 +6978 +10743 +19161 +12308 +9509 +13233 +4666 +5850 +17040 +2473 +17323 +6728 +11500 +4401 +13887 +19944 +17601 +19731 +10715 +8327 +11196 +7944 +9068 +13253 +13913 +13419 +17649 +16894 +3333 +5747 +3000 +12724 +17772 +17341 +11854 +6042 +10362 +3438 +13828 +471 +17747 +13707 +17902 +8184 +3385 +19387 +46 +1848 +15848 +10768 +17481 +436 +17581 +4629 +13210 +5085 +19485 +44 +12549 +16407 +9646 +9884 +15802 +2461 +15134 +2936 +8156 +17411 +1228 +18200 +14616 +17443 +5512 +6017 +10137 +11424 +11940 +6655 +17669 +6147 +16570 +17281 +18915 +19689 +18013 +17895 +6925 +19766 +18634 +7195 +7001 +12335 +3908 +18754 +4833 +12486 +12892 +18879 +3691 +1693 +158 +8682 +1029 +3429 +644 +1664 +13972 +5352 +15422 +1928 +14561 +3322 +3570 +6298 +2251 +12216 +19823 +12658 +2081 +4177 +13843 +18454 +13755 +9340 +6373 +3290 +2893 +16274 +16610 +12782 +7269 +5681 +19372 +7843 +14844 +16236 +16004 +1136 +5759 +19347 +7684 +7435 +5892 +7305 +2504 +7064 +13264 +8781 +1327 +19943 +18122 +1803 +9999 +13695 +9742 +8274 +744 +2252 +10524 +1434 +4601 +6071 +10489 +19626 +10745 +18312 +872 +19166 +3417 +9272 +1433 +9431 +6486 +3532 +18452 +17830 +9835 +2495 +10475 +16725 +16019 +6594 +11355 +13055 +14782 +11924 +18838 +3563 +428 +12993 +14223 +6658 +2783 +1726 +6929 +13053 +19175 +8564 +4867 +19604 +17416 +9347 +2275 +16381 +9817 +11176 +14576 +6906 +9805 +14149 +2241 +11030 +453 +835 +15452 +2879 +4018 +17396 +16133 +1301 +3450 +10182 +2389 +19201 +4443 +14368 +2537 +7452 +1583 +13955 +3875 +7479 +17561 +3247 +16310 +5253 +8899 +6523 +10260 +13065 +11077 +15109 +7249 +12046 +5313 +8914 +19949 +2196 +3654 +7145 +12166 +18340 +17929 +12466 +7866 +3831 +15095 +2506 +17691 +12992 +6591 +9661 +19538 +2161 +3991 +6766 +18180 +182 +15952 +9709 +19601 +13427 +19071 +12698 +12157 +7963 +3485 +19327 +6029 +12948 +2261 +2844 +4864 +12148 +9187 +6695 +8171 +19771 +3782 +14122 +11658 +330 +10750 +6932 +4436 +15622 +5710 +18750 +5765 +10545 +10897 +16609 +9183 +802 +14708 +3423 +11557 +19098 +3641 +14490 +3249 +1355 +16886 +18500 +15309 +8010 +18543 +2342 +3813 +2135 +9055 +15148 +12720 +3253 +737 +11788 +253 +13352 +1521 +13949 +1957 +10884 +2273 +14730 +13979 +2401 +595 +12697 +9932 +11372 +11915 +760 +10930 +10659 +6472 +19706 +6488 +9730 +17705 +16085 +4134 +2070 +4852 +5122 +16359 +7044 +8510 +10868 +10172 +510 +11550 +260 +11181 +3018 +3668 +904 +10271 +17104 +12764 +3364 +1878 +2803 +14040 +1149 +15626 +12809 +11008 +2903 +8352 +12761 +13470 +11258 +1400 +8381 +12422 +8402 +3919 +7164 +17263 +18167 +4549 +7654 +6034 +8438 +19451 +12122 +5167 +19334 +9771 +1111 +2932 +18324 +4897 +12687 +1720 +2767 +7616 +6431 +16918 +579 +16504 +4559 +14384 +6337 +4008 +7937 +1086 +5314 +12489 +5211 +17500 +19641 +14815 +7967 +8140 +5239 +2571 +18601 +16197 +5142 +12714 +14895 +3432 +3995 +9206 +7668 +8703 +1661 +4315 +5941 +6849 +2505 +19547 +11736 +5319 +986 +7846 +16050 +9227 +13121 +1012 +18236 +4888 +3885 +11135 +17395 +4303 +3836 +18544 +9807 +15248 +10626 +13846 +17286 +5581 +14007 +2062 +4619 +14864 +13869 +2442 +17728 +11590 +16382 +19117 +19446 +6843 +8694 +14439 +3453 +2700 +9821 +8089 +9645 +14679 +4356 +11980 +5408 +2668 +8053 +1647 +19959 +17083 +14916 +8841 +2319 +11984 +12867 +4292 +4633 +1492 +10716 +12880 +8243 +3929 +2225 +2943 +17578 +12138 +5648 +9614 +15487 +18868 +10779 +12716 +403 +2908 +7040 +4772 +19912 +14823 +5045 +14250 +19733 +13073 +6947 +10387 +8021 +5201 +4488 +18161 +4100 +1422 +16865 +7646 +4370 +17271 +19121 +9808 +2613 +15130 +18893 +11654 +5903 +15058 +12954 +6480 +5764 +15830 +17813 +10224 +6324 +4412 +5607 +9497 +7849 +1291 +9401 +19126 +15067 +10197 +18480 +6258 +8590 +17216 +7437 +16511 +18807 +4267 +18809 +14488 +2345 +4395 +11054 +7624 +3708 +896 +18870 +19517 +2950 +7950 +19529 +155 +19786 +138 +7168 +2130 +10699 +19821 +19156 +11071 +8912 +9515 +17234 +10388 +195 +19909 +16687 +18628 +5870 +10436 +16939 +6562 +8748 +4929 +6282 +9147 +12262 +18067 +17029 +5593 +11043 +15042 +19516 +7618 +13353 +3793 +108 +8255 +8446 +9675 +6111 +5162 +17668 +11558 +17151 +4502 +4353 +19681 +9842 +9229 +13095 +6533 +5706 +14713 +130 +4435 +918 +5195 +4348 +13863 +1247 +13221 +11826 +14356 +7315 +19382 +14025 +10586 +13495 +2418 +13930 +17352 +10751 +5332 +19001 +148 +12921 +8219 +11851 +12210 +5136 +16621 +309 +11602 +3224 +2787 +831 +2423 +14749 +12053 +9389 +15413 +17125 +7143 +19332 +10719 +10433 +4229 +6003 +3725 +17978 +3086 +17007 +6993 +16758 +6015 +16832 +2292 +16344 +13161 +7474 +12363 +10615 +19599 +6856 +10583 +19326 +15872 +3318 +17397 +14798 +8994 +13566 +949 +8506 +17722 +14915 +16273 +14643 +12334 +6859 +3148 +16594 +1809 +16350 +10681 +5696 +19560 +11625 +12856 +14535 +12292 +10444 +14707 +19226 +15085 +17377 +10766 +1833 +14675 +6297 +11865 +9647 +1269 +11299 +18222 +12310 +5715 +3293 +5580 +16180 +3198 +5655 +14952 +4632 +18179 +14464 +18546 +19062 +14401 +10772 +11719 +12926 +6267 +9163 +7559 +6358 +6903 +12503 +842 +90 +11725 +5854 +2083 +9137 +3292 +2781 +10855 +13137 +1993 +6499 +1395 +4910 +9378 +445 +13443 +7039 +15416 +7434 +13093 +14981 +10377 +13571 +5652 +19404 +14335 +8636 +13404 +18715 +12722 +19189 +9989 +12956 +7993 +7848 +5771 +16660 +9063 +8452 +4845 +14997 +6883 +11982 +1931 +9618 +11593 +12712 +16973 +17452 +9993 +3728 +18598 +15326 +15360 +7612 +18837 +5048 +9659 +14572 +732 +10948 +8383 +15938 +9822 +15502 +231 +9438 +13629 +4987 +16527 +7250 +17364 +14600 +13817 +7983 +7154 +4103 +14313 +6931 +13983 +14009 +11778 +5478 +11543 +13446 +13037 +17142 +8307 +17676 +16495 +2274 +15324 +8828 +7999 +861 +6566 +17141 +9039 +694 +2882 +10144 +17051 +15743 +11263 +17156 +9122 +9916 +14398 +7063 +6237 +5638 +15763 +1781 +2049 +10105 +1246 +7266 +7500 +18846 +5535 +15135 +18616 +10987 +4354 +18659 +18721 +4950 +14666 +12702 +663 +11894 +11411 +19965 +3137 +5388 +7768 +5069 +7826 +19221 +1176 +18638 +3314 +36 +17709 +15578 +14710 +4791 +6413 +5461 +7776 +13204 +2302 +6382 +9622 +8769 +8967 +4208 +15083 +2464 +9639 +19391 +14833 +9760 +1577 +681 +236 +1985 +12792 +10147 +11477 +14536 +8012 +18444 +13183 +7810 +7717 +8593 +1654 +18958 +19769 +5659 +13596 +8469 +17760 +16629 +17402 +2140 +16696 +14869 +8103 +18250 +6429 +469 +7934 +16281 +16623 +7074 +4984 +9624 +16339 +7825 +19700 +6866 +15914 +19964 +19336 +13712 +11268 +3216 +10218 +12589 +4453 +14596 +16420 +1512 +18977 +11886 +11637 +12934 +496 +18503 +7326 +1082 +19257 +12682 +5177 +12065 +1500 +8097 +17636 +1973 +12448 +2209 +6165 +17875 +13036 +11911 +17546 +18476 +14284 +12114 +15674 +7720 +3484 +10471 +6089 +3441 +12887 +19772 +5168 +16222 +18075 +6793 +1074 +3428 +7593 +8465 +14048 +3463 +15554 +15329 +4352 +6135 +11756 +4268 +1482 +3523 +14390 +3681 +3090 +15748 +2656 +9255 +6536 +10528 +8574 +1926 +18022 +8625 +19593 +12288 +10632 +18212 +9782 +1875 +2082 +13643 +16171 +8385 +15465 +5751 +9420 +1004 +7771 +12499 +12525 +6097 +1513 +15921 +15484 +12663 +17072 +4693 +15491 +9584 +5864 +4977 +7841 +15412 +7923 +3536 +2540 +6911 +10031 +2206 +18931 +1856 +205 +8152 +12603 +4552 +19026 +9223 +10389 +11271 +16914 +16266 +9829 +8124 +3549 +11605 +16055 +5537 +19801 +11601 +3499 +7699 +735 +9037 +18773 +11078 +18295 +11935 +16267 +5072 +1822 +16710 +5097 +2812 +13191 +12077 +9819 +5524 +17767 +10587 +10513 +1994 +19862 +18907 +7968 +15272 +7789 +2409 +54 +19531 +8092 +3347 +673 +5449 +18599 +11457 +9023 +18216 +151 +3325 +7491 +12272 +1089 +17925 +12543 +4855 +910 +8895 +2662 +17435 +11455 +6263 +6049 +10308 +14696 +1120 +1857 +14658 +14709 +1827 +9133 +3732 +2308 +5021 +19895 +5130 +2321 +8478 +13751 +14668 +12758 +6368 +925 +6567 +13960 +4392 +17533 +11140 +8696 +4902 +19715 +19592 +19009 +6990 +7368 +2884 +1761 +9096 +5776 +19203 +12034 +13669 +14639 +8126 +11779 +16533 +1682 +208 +7340 +6351 +6564 +16168 +11449 +15859 +14482 +19057 +13581 +5965 +18130 +1427 +8670 +16155 +17607 +3754 +5050 +8369 +10157 +7623 +4580 +10289 +14147 +4613 +6316 +8441 +13630 +19850 +15986 +1160 +17770 +19266 +83 +6643 +4694 +10353 +4909 +4727 +15659 +5584 +2641 +3698 +3165 +13039 +13312 +4756 +3598 +8958 +1898 +16121 +18728 +6332 +6539 +12401 +18019 +13123 +15388 +1972 +3111 +13250 +13944 +15408 +9078 +452 +14346 +7560 +2306 +3883 +6312 +3541 +5518 +3377 +19440 +11416 +6459 +19730 +1018 +17717 +19070 +2979 +7628 +3294 +14038 +17208 +16535 +14850 +7 +16427 +18239 +5066 +9609 +9194 +11734 +14200 +4917 +13090 +2490 +3735 +3829 +13487 +7105 +4108 +450 +10527 +3391 +13080 +3884 +9246 +14599 +12759 +9940 +5528 +1425 +3209 +4 +11016 +14852 +17253 +15713 +4653 +5849 +4787 +16819 +12491 +19370 +12594 +3657 +10088 +3741 +9981 +3779 +18367 +4760 +8416 +16092 +18242 +12718 +18491 +13873 +10163 +11696 +4073 +1570 +18443 +8328 +3675 +4282 +7763 +6861 +17516 +18429 +7823 +11156 +9205 +18297 +13738 +7811 +3578 +8944 +2115 +16468 +3907 +15293 +10044 +6555 +2826 +9838 +6750 +15892 +4279 +6867 +7938 +9788 +1115 +13625 +2146 +11581 +1096 +18237 +10236 +9201 +17460 +13171 +9963 +7202 +3966 +4294 +5573 +10232 +13791 +19875 +9298 +11298 +18253 +10352 +14014 +10952 +16802 +17984 +3027 +11733 +3150 +3514 +5796 +16181 +16322 +15572 +9196 +9392 +6842 +13963 +7868 +4416 +5411 +4598 +12392 +8187 +8809 +1722 +14154 +7136 +10114 +806 +4506 +2210 +1234 +6487 +12601 +6345 +1222 +11032 +17837 +1436 +18510 +13192 +13409 +2916 +15236 +2171 +19849 +18365 +13536 +7186 +18356 +13562 +13042 +15819 +11301 +5777 +15869 +9462 +264 +6749 +6724 +19018 +3737 +4210 +13420 +16942 +8870 +14209 +19898 +882 +4021 +18094 +438 +15220 +12025 +19916 +8802 +16090 +7216 +13396 +19431 +15182 +11773 +2064 +2735 +4187 +14432 +6551 +14174 +4687 +14750 +19246 +5868 +8400 +16515 +3028 +1855 +15898 +12605 +2643 +9103 +7130 +10895 +9089 +2771 +19857 +10033 +19263 +9119 +14706 +14207 +18470 +11743 +18163 +859 +13245 +14698 +11764 +9748 +15584 +19089 +13388 +18928 +3289 +19660 +16732 +16194 +70 +19077 +2745 +11216 +5550 +15300 +7565 +1766 +9684 +18285 +3060 +14989 +5227 +2072 +8080 +14517 +12391 +13686 +7525 +14548 +11403 +8754 +16046 +10953 +7112 +5592 +6882 +9080 +4589 +13437 +16114 +5753 +6118 +16947 +4566 +9633 +7033 +13356 +9164 +13671 +9689 +11207 +18007 +2402 +15376 +16038 +6571 +4875 +3055 +16146 +18484 +19778 +12574 +966 +16007 +6908 +10248 +9118 +1820 +1830 +14591 +15893 +13881 +6987 +5794 +13255 +12003 +4537 +18485 +3567 +7203 +19079 +6338 +8671 +15590 +19654 +2552 +10446 +14189 +3207 +9582 +12209 +18993 +6941 +14448 +18639 +18694 +5814 +10292 +8377 +10796 +10680 +15 +870 +1777 +15404 +2044 +4232 +3917 +5371 +7725 +8974 +8227 +6073 +12404 +9084 +19466 +14267 +8223 +7381 +7682 +632 +12671 +1325 +11845 +11113 +8412 +19417 +6357 +17205 +380 +4919 +7842 +14100 +16317 +15235 +14613 +18211 +7461 +19872 +9913 +11784 +13436 +1859 +6597 +13750 +10136 +14029 +10842 +1795 +682 +11266 +16047 +5758 +1194 +16086 +7301 +6798 +10818 +3495 +17518 +298 +16767 +18903 +15113 +10358 +5676 +18567 +4812 +15165 +9477 +2283 +11622 +13722 +3073 +16187 +2544 +2482 +7534 +18691 +14260 +274 +14682 +3231 +16237 +6606 +16494 +12612 +17826 +18266 +17652 +11954 +19394 +16356 +15781 +6498 +7613 +18308 +9852 +12495 +11569 +6822 +15384 +18414 +16240 +17425 +3619 +2998 +4060 +281 +12126 +13552 +17956 +8648 +5199 +11470 +19559 +2184 +4127 +1782 +11302 +8272 +7227 +4378 +6617 +17001 +5565 +12212 +15110 +12717 +9177 +203 +15928 +14386 +18671 +3664 +5577 +5825 +18883 +11563 +7790 +16821 +19075 +11407 +4067 +481 +15007 +10607 +1437 +16173 +10793 +647 +3305 +2691 +15054 +1132 +8766 +14500 +14137 +11852 +14871 +765 +16596 +1727 +2747 +9784 +9337 +16309 +16810 +16508 +12105 +1127 +13997 +17502 +17305 +18799 +12701 +5281 +13678 +4044 +18969 +14380 +19526 +15873 +8501 +299 +1764 +18487 +19620 +4094 +9237 +12970 +4240 +14861 +11285 +1470 +3766 +9496 +9656 +5356 +7509 +9637 +15046 +19038 +1072 +13336 +784 +18523 +6996 +15991 +581 +14929 +16799 +4522 +8701 +9889 +5016 +7199 +19270 +15705 +2611 +10397 +19448 +17801 +11447 +16190 +16130 +3153 +12318 +5677 +14727 +13117 +9800 +15894 +15709 +9081 +5403 +15579 +6359 +5576 +552 +19272 +11427 +4343 +11192 +12732 +4424 +17024 +7715 +12633 +2562 +12400 +4330 +16677 +1150 +6402 +18957 +9338 +4726 +10064 +8644 +17968 +79 +14922 +12178 +7837 +11881 +18551 +2096 +7547 +6879 +16607 +17532 +17944 +10284 +10009 +9868 +2088 +7165 +17038 +14403 +11088 +9668 +13714 +9125 +13804 +13547 +200 +11058 +19642 +3016 +5375 +14376 +5202 +3268 +8476 +14820 +12021 +17213 +12957 +8549 +15190 +5397 +3339 +8084 +15262 +10297 +14127 +18950 +14402 +11073 +5657 +10318 +13866 +9180 +18302 +3183 +2397 +11747 +9357 +2022 +10447 +16582 +19247 +14261 +19923 +14503 +16422 +8778 +18439 +19673 +1679 +9156 +14756 +8836 +792 +14801 +14510 +4556 +12417 +6110 +15972 +1030 +2328 +525 +16238 +11164 +11570 +17610 +4118 +11897 +9444 +14758 +2978 +16124 +7333 +6201 +14646 +819 +16867 +758 +4095 +19080 +15720 +17338 +18410 +12800 +16679 +10495 +6063 +10001 +18512 +14521 +6137 +18160 +5900 +3606 +15776 +9127 +13491 +17690 +9173 +5013 +3745 +13371 +9315 +4604 +14737 +4625 +7850 +3071 +2681 +13915 +3716 +7617 +12597 +3512 +3565 +19435 +7564 +17592 +9035 +12394 +2941 +6473 +13995 +18469 +11981 +17680 +1932 +19172 +1959 +16466 +2043 +11677 +7471 +7635 +12870 +10337 +15199 +2517 +17905 +10239 +5615 +2269 +13794 +2664 +8883 +10087 +9073 +10617 +5548 +10940 +19822 +11659 +13147 +12171 +3164 +17034 +9484 +17682 +7142 +3559 +12980 +11388 +7572 +17292 +3311 +3561 +7590 +14998 +7454 +2874 +6168 +937 +14366 +8090 +8710 +12599 +8443 +8970 +18892 +329 +3254 +7781 +16904 +4896 +12343 +11478 +10553 +4132 +17450 +12864 +3510 +1402 +12055 +8183 +165 +9948 +3214 +6878 +5933 +228 +3230 +1281 +15215 +10404 +3367 +4014 +6632 +9043 +4818 +6661 +19398 +18517 +7085 +17011 +13682 +15769 +13317 +3843 +11294 +7302 +8179 +12539 +16626 +3607 +15203 +2254 +5182 +16659 +12406 +12573 +5917 +2373 +11062 +17231 +3916 +3105 +9085 +18613 +11408 +17161 +17366 +11591 +4238 +4660 +2848 +5891 +12804 +10288 +8174 +14239 +12514 +4654 +4250 +2852 +6314 +2368 +4331 +10102 +9215 +4154 +9775 +15534 +16486 +6072 +17897 +6804 +9025 +6688 +8484 +7362 +7728 +18465 +17285 +7308 +13520 +11839 +8577 +3723 +4068 +5628 +18978 +9294 +13440 +3112 +13821 +12027 +13670 +1564 +15275 +10179 +9740 +7109 +8716 +11499 +11306 +4092 +15096 +18461 +19703 +15349 +1079 +15249 +4831 +8609 +5402 +6252 +12462 +17598 +8256 +4873 +901 +1505 +10888 +13587 +16191 +1683 +13035 +13771 +4377 +17164 +4385 +9517 +18346 +10202 +807 +3176 +3393 +10311 +11856 +4420 +17807 +16514 +17296 +10185 +7689 +2121 +603 +19848 +14957 +6235 +3765 +6958 +16961 +16835 +11823 +15218 +3673 +14694 +9799 +10988 +11521 +16713 +2904 +6079 +3201 +18911 +4517 +5304 +6689 +3034 +17456 +14288 +3025 +9030 +10834 +72 +3640 +5419 +17997 +12664 +17332 +3392 +18034 +8415 +10580 +2582 +7067 +12922 +8116 +6069 +9456 +3945 +12121 +3205 +1471 +18203 +4563 +11758 +15828 +12696 +3029 +5878 +7584 +18021 +9781 +13367 +12159 +8708 +17930 +18482 +3810 +19468 +9992 +9466 +16650 +8319 +8075 +13026 +12750 +4248 +3756 +6904 +5987 +10300 +19513 +7835 +14553 +7997 +13118 +13895 +14201 +828 +19873 +14254 +14321 +6442 +7713 +18594 +9283 +3803 +18739 +5800 +8088 +11797 +12172 +17438 +8013 +6444 +2526 +19303 +7752 +5243 +10222 +14888 +1987 +12728 +2281 +14094 +13189 +18421 +232 +17792 +12315 +5112 +10252 +14472 +11282 +13205 +8666 +16375 +13298 +53 +16122 +15019 +18453 +11551 +17430 +10461 +11789 +5997 +2790 +18547 +12547 +6067 +19149 +2820 +18032 +10802 +10133 +18017 +7667 +13452 +16972 +4192 +2519 +15381 +12924 +10438 +19016 +4955 +3903 +10237 +15152 +2860 +19938 +5412 +14294 +2867 +15553 +8672 +13106 +11603 +408 +546 +6437 +7921 +7487 +11587 +14507 +4111 +15628 +13295 +8340 +18279 +7259 +14649 +19506 +14785 +10293 +14742 +19136 +6265 +1087 +12052 +15843 +18727 +5484 +845 +15185 +13976 +15646 +17664 +1068 +4335 +8722 +12020 +488 +2706 +282 +3534 +1294 +3043 +11397 +2713 +2975 +944 +10208 +100 +19744 +4924 +2107 +17519 +7385 +2507 +17006 +2763 +7137 +17314 +15094 +12296 +12237 +10544 +2758 +76 +12678 +10763 +3780 +17067 +8968 +975 +3659 +13505 +15863 +17766 +3363 +5423 +7463 +2178 +4126 +14612 +7382 +19859 +676 +12313 +9295 +8640 +11309 +10754 +13801 +12608 +13889 +18117 +16269 +3412 +10649 +12279 +3508 +7951 +13929 +12250 +17637 +8922 +18762 +18329 +14702 +9507 +19961 +850 +9597 +4414 +13247 +16822 +10422 +19205 +3713 +3436 +7248 +4243 +10902 +8762 +15545 +12653 +18681 +13455 +14691 +10967 +3489 +18920 +12677 +9470 +2134 +15958 +350 +19280 +17241 +19725 +3551 +7246 +19535 +7724 +18758 +1731 +3332 +17522 +467 +2625 +9608 +14969 +1323 +9233 +16160 +14099 +5302 +8554 +4449 +5333 +9273 +16185 +14522 +17604 +19605 +6303 +12330 +15146 +14008 +7440 +541 +11439 +1576 +16787 +16643 +3187 +1217 +9606 +833 +7777 +15549 +18991 +11612 +4806 +5366 +12275 +19215 +19449 +12385 +8947 +15472 +13739 +14947 +1225 +12670 +6053 +2155 +5435 +15931 +13807 +16673 +8413 +15099 +10069 +13744 +9676 +12002 +16917 +1192 +13262 +15795 +12097 +4419 +2704 +15031 +10581 +13753 +5473 +721 +8536 +15470 +12176 +11335 +3264 +1075 +3213 +12203 +1035 +18985 +621 +4571 +832 +18668 +1008 +6614 +10274 +7827 +18731 +2421 +10075 +15523 +2499 +3761 +13927 +7374 +2263 +4507 +209 +8779 +492 +9195 +18556 +10960 +16021 +10464 +5662 +18906 +13364 +13332 +13413 +8647 +2909 +6985 +16880 +16692 +17599 +788 +14233 +7122 +14248 +14319 +9678 +7149 +10526 +1587 +19510 +5975 +4104 +3319 +9437 +996 +4384 +6922 +5501 +17736 +3483 +7518 +8495 +368 +1461 +9559 +15729 +6638 +5407 +13111 +14491 +8824 +6615 +2284 +14186 +10279 +11785 +10097 +16919 +14273 +15533 +4079 +18344 +2175 +15635 +14883 +4928 +8034 +19930 +13460 +5421 +8072 +18176 +18157 +14272 +6271 +15237 +8601 +12886 +8145 +3390 +11900 +8524 +3615 +3893 +17727 +3817 +16812 +1177 +19385 +2759 +14657 +11853 +19444 +12660 +3987 +2960 +16110 +12808 +1706 +9939 +11800 +4441 +14638 +459 +13076 +18192 +10061 +18226 +8324 +19067 +17264 +14165 +19323 +3747 +9056 +4321 +9546 +8030 +2356 +18989 +16340 +11970 +16797 +14564 +5216 +359 +1881 +17087 +11333 +18725 +10957 +5118 +2959 +4838 +12425 +14879 +11620 +5585 +12994 +3695 +18873 +2286 +10737 +16869 +11498 +18970 +4309 +772 +4029 +18787 +8505 +4596 +2731 +12749 +1349 +16805 +7028 +14818 +5098 +7543 +6474 +8697 +4439 +5308 +12946 +18423 +13965 +11975 +2260 +7046 +17257 +15904 +1114 +7306 +5780 +2764 +8788 +19176 +15016 +7772 +5060 +10836 +9873 +11267 +10981 +8305 +5044 +5872 +19841 +7894 +8600 +19411 +5946 +13648 +255 +2447 +1558 +490 +17820 +17806 +15541 +893 +6841 +15371 +11170 +10039 +9423 +17294 +18620 +8311 +17065 +968 +3834 +545 +16969 +12174 +4056 +16630 +8260 +8432 +10238 +14779 +4390 +2883 +14841 +10338 +13475 +7354 +14736 +13167 +2772 +18162 +15228 +12305 +12719 +1644 +10361 +7441 +17815 +11553 +8711 +1066 +5487 +9175 +9275 +5210 +18973 +13240 +17780 +2550 +12982 +14832 +10927 +4661 +16513 +12471 +15925 +2872 +12541 +17750 +18498 +6578 +3611 +17994 +13313 +22 +18334 +2349 +1415 +16900 +13975 +3906 +7735 +9625 +11194 +18855 +11188 +16154 +10403 +3064 +15075 +1773 +5986 +8845 +12083 +920 +3050 +17827 +5658 +16020 +17909 +7881 +4933 +12873 +8433 +8631 +18760 +15821 +7722 +11460 +17342 +2034 +17490 +10780 +883 +14097 +15098 +14621 +6636 +5720 +1124 +16757 +10874 +15537 +1557 +10173 +17788 +1749 +8910 +13488 +11561 +18073 +15930 +12831 +14569 +2545 +11320 +11238 +19196 +3753 +12191 +1336 +17805 +8758 +8200 +7914 +2095 +8798 +6651 +11808 +2970 +19186 +15383 +19024 +8654 +14744 +12256 +1023 +963 +7280 +8548 +11983 +1423 +3704 +17529 +10627 +743 +3001 +16400 +5489 +5010 +180 +5853 +13238 +12358 +15963 +14717 +11350 +3159 +18665 +14449 +15660 +19809 +18975 +2655 +306 +4030 +7739 +8509 +14567 +8664 +9500 +13230 +16056 +567 +15875 +2716 +18559 +17496 +1212 +8394 +1828 +864 +16868 +16018 +4259 +2470 +10454 +14166 +5460 +4926 +10011 +3869 +1324 +13729 +5361 +11782 +9954 +10348 +16472 +11978 +10548 +2312 +14032 +4262 +4674 +1050 +855 +6933 +18283 +15984 +15960 +609 +5280 +7784 +3261 +10588 +13579 +19058 +13563 +15211 +17376 +18894 +13797 +14550 +15929 +11391 +19746 +2497 +2762 +5351 +3573 +7663 +13316 +5052 +18248 +10496 +9108 +17914 +1589 +10976 +12564 +5640 +7052 +3650 +19288 +17354 +5334 +1612 +8429 +19457 +12336 +844 +17372 +2722 +4020 +13935 +2141 +13269 +4597 +14880 +17706 +10707 +4160 +8588 +7049 +909 +17520 +17317 +18777 +10 +18364 +11199 +17916 +11227 +1696 +14325 +12214 +7281 +14539 +16857 +1591 +6780 +6432 +8874 +10189 +9146 +15350 +5802 +18704 +2868 +4437 +172 +4893 +14474 +13974 +13089 +5457 +10797 +13858 +6339 +821 +8035 +10046 +14123 +19109 +15420 +16257 +11615 +7462 +8867 +8253 +13737 +20 +107 +17031 +13078 +8634 +1974 +14051 +16800 +8299 +19040 +17896 +9109 +7124 +12631 +17931 +1890 +6823 +8000 +4767 +2295 +15732 +1915 +10664 +15103 +9049 +18741 +17887 +3320 +12120 +9574 +17724 +9563 +6734 +2316 +31 +3671 +4605 +1084 +9813 +6435 +520 +19309 +3978 +6141 +17935 +6068 +18886 +3372 +4828 +99 +14056 +13544 +17509 +853 +14034 +18028 +11904 +16706 +11293 +8434 +7642 +12996 +14371 +3298 +17073 +267 +18636 +6920 +4529 +4574 +8390 +11360 +5255 +5601 +12248 +10778 +13658 +5784 +5476 +7671 +19286 +18144 +1927 +14367 +6863 +3805 +17986 +16333 +3227 +18191 +3301 +18071 +7150 +8780 +13907 +12393 +16166 +11973 +15147 +9541 +14193 +7318 +3712 +13708 +11345 +10427 +4323 +12026 +10245 +19967 +1405 +388 +16958 +2546 +7439 +10000 +16496 +16774 +6023 +16728 +13478 +2087 +11657 +14383 +4916 +18463 +4677 +4421 +17658 +8330 +1958 +11352 +7005 +19148 +5629 +14120 +5343 +10312 +18412 +17808 +770 +13891 +7283 +1547 +19493 +8091 +13424 +303 +3252 +12888 +2924 +12908 +13878 +13442 +15359 +5838 +11929 +5483 +8948 +15000 +8852 +12754 +7103 +17378 +1990 +2635 +1314 +19376 +10616 +10319 +569 +16644 +18499 +6572 +7071 +8093 +2218 +7749 +8333 +3011 +6260 +3358 +13649 +3821 +11575 +17623 +8707 +19293 +9585 +16920 +16461 +15377 +19556 +8660 +11807 +9534 +12326 +6289 +16950 +12742 +7347 +339 +12876 +15013 +6976 +16105 +15043 +18193 +1348 +14931 +583 +19476 +8455 +7530 +13897 +13373 +13684 +13655 +5635 +9475 +377 +16225 +12223 +17025 +13706 +11763 +8756 +834 +10618 +19095 +11740 +15561 +7160 +11522 +8688 +7273 +4477 +14811 +9832 +12352 +14281 +7299 +8576 +1020 +2961 +12276 +1193 +16897 +3473 +1185 +1198 +1353 +12881 +4077 +15642 +5511 +12840 +9750 +13101 +8026 +2282 +14224 +5480 +10594 +9903 +16358 +458 +18927 +19045 +9355 +7312 +3094 +12584 +6116 +16287 +3091 +967 +19947 +5920 +5979 +4883 +11583 +15033 +2160 +3479 +15639 +1204 +16521 +2777 +13765 +3517 +18076 +16376 +4802 +1197 +11109 +11985 +7585 +11451 +19169 +10648 +18223 +9554 +18688 +16116 +19412 +19371 +17483 +10726 +13054 +15421 +15637 +5861 +2355 +6874 +2054 +8052 +4763 +5086 +17479 +16568 +286 +11314 +5630 +7638 +4785 +18259 +15063 +5927 +1902 +9487 +4430 +12127 +7984 +5323 +14082 +10574 +11798 +19408 +13315 +17400 +12810 +6405 +10885 +18982 +6347 +6107 +12879 +14257 +6212 +5437 +12789 +17322 +2320 +17370 +1352 +14275 +8316 +19375 +2163 +10911 +12257 +13001 +3599 +13911 +12429 +5992 +16178 +11690 +6844 +10925 +11040 +13829 +3140 +5848 +18252 +14050 +18210 +13620 +4801 +6090 +8264 +1200 +13511 +14581 +18087 +15366 +4711 +5058 +18509 +10826 +10217 +19119 +6825 +12066 +17167 +2869 +262 +14434 +2468 +11247 +4607 +16667 +4655 +4009 +19788 +11664 +15257 +3981 +11512 +18254 +241 +14508 +5385 +14884 +508 +1010 +3533 +9474 +12500 +476 +19878 +8245 +6221 +16128 +11381 +13202 +13770 +9372 +15750 +9753 +12263 +7979 +8317 +16030 +1428 +3304 +5890 +10040 +16840 +11006 +103 +15437 +1237 +11452 +6471 +14688 +815 +10416 +14624 +15082 +12329 +10168 +7885 +8055 +6173 +1700 +14259 +19945 +3396 +11197 +5867 +14058 +2610 +7808 +18272 +19800 +11895 +5748 +5678 +19439 +18288 +7690 +17950 +4670 +6855 +13832 +2375 +16247 +11035 +8411 +7119 +8172 +19577 +18407 +16033 +9886 +618 +6757 +8663 +7024 +4404 +3775 +5904 +3496 +11175 +1178 +18651 +540 +14839 +715 +14427 +19913 +11250 +10014 +18733 +1745 +8873 +19741 +17799 +19854 +17954 +1250 +10275 +9579 +1962 +7512 +15141 +4980 +7405 +8585 +10711 +16475 +11717 +18530 +7008 +17316 +2051 +17537 +13796 +1477 +7907 +6230 +8903 +15358 +17492 +12721 +12635 +9425 +7215 +4657 +15880 +5509 +9729 +5597 +15150 +928 +4194 +1885 +3352 +8450 +12802 +4699 +12373 +19727 +1007 +6365 +5531 +4505 +5181 +6139 +2523 +10598 +10730 +12987 +2547 +3516 +680 +18052 +19078 +4568 +18027 +2796 +1980 +19124 +7240 +10159 +19131 +17431 +8023 +2190 +13260 +5143 +7262 +5203 +1040 +509 +8107 +6132 +547 +7740 +865 +3225 +14348 +3 +17698 +4518 +14070 +8993 +3922 +15050 +7829 +15039 +9427 +18434 +2757 +6380 +6816 +19475 +4465 +1804 +19770 +10633 +6774 +768 +5538 +14069 +4741 +18234 +16102 +7251 +2454 +18843 +9332 +5262 +16198 +9344 +2407 +10856 +1814 +12693 +3466 +12384 +14777 +2629 +16280 +9697 +6262 +6032 +6644 +5723 +8028 +8690 +13169 +19321 +3191 +2749 +10658 +8676 +4347 +17068 +19545 +2317 +2813 +8048 +17365 +16087 +5632 +7524 +5071 +16539 +3634 +18685 +1946 +12445 +16760 +18307 +8191 +6206 +18602 +2410 +11873 +8244 +2398 +9473 +19936 +14607 +13920 +4149 +17223 +13809 +9226 +5991 +16764 +19141 +5709 +8294 +1017 +14026 +13389 +10963 +19174 +8850 +16622 +8344 +11248 +3721 +16117 +5731 +2810 +12726 +3596 +3072 +18576 +13369 +5425 +5430 +8846 +15783 +9879 +12443 +4728 +17085 +3188 +16256 +15425 +19267 +1227 +6170 +12137 +4440 +10004 +7949 +8129 +11707 +11220 +1256 +17421 +2007 +1174 +10396 +16049 +9773 +606 +2132 +9313 +5728 +4251 +14010 +10174 +16283 +3203 +11755 +2623 +2621 +15918 +18477 +14574 +6723 +5389 +14221 +7239 +2113 +16454 +16901 +6715 +4547 +12311 +19231 +15456 +18515 +5515 +245 +13456 +15386 +19927 +13823 +13702 +19978 +12766 +8962 +18392 +11673 +12983 +19551 +11223 +12740 +5505 +5675 +3331 +3480 +15799 +19170 +14468 +160 +19132 +6284 +19458 +16980 +1611 +15836 +2937 +10568 +14133 +7288 +13865 +13763 +19851 +16933 +12944 +10334 +9367 +8276 +11863 +9117 +2688 +16561 +13508 +14352 +13068 +4508 +14538 +13431 +5919 +17369 +12828 +13981 +2997 +16843 +4373 +8359 +15842 +12756 +2176 +13393 +811 +3988 +19814 +5265 +14033 +10860 +9549 +8273 +5788 +1121 +18359 +16169 +5434 +1772 +18744 +1245 +11874 +7131 +15168 +2703 +3079 +18947 +12397 +11053 +14900 +13163 +18433 +9651 +1265 +3100 +12452 +688 +18261 +19883 +14141 +4545 +16244 +2580 +9951 +16887 +9712 +2110 +17558 +13218 +5065 +4403 +2004 +18790 +17525 +285 +19661 +3891 +14106 +4975 +1769 +2406 +2606 +9744 +19775 +6918 +15410 +16248 +13083 +5247 +16733 +4649 +7420 +19254 +2432 +11139 +16608 +2 +11832 +7230 +1347 +16937 +15047 +3078 +9306 +6563 +10611 +5911 +7459 +634 +17381 +18323 +15443 +12902 +16385 +17239 +12229 +12747 +13786 +16923 +123 +11850 +17773 +12220 +14943 +4254 +3024 +6683 +9112 +9558 +16065 +9754 +6114 +10785 +9192 +15021 +4091 +10762 +3976 +13894 +7588 +13490 +2973 +3498 +6313 +14176 +12108 +3786 +17893 +5156 +18260 +7296 +4740 +15948 +10610 +12735 +5967 +2618 +7175 +558 +16931 +14886 +17757 +13469 +1182 +4252 +16241 +13638 +6514 +12370 +917 +18078 +16360 +8323 +8702 +7892 +1787 +9268 +12665 +16747 +8786 +10053 +4096 +4359 +9432 +12741 +4991 +9333 +12123 +1365 +1734 +8892 +804 +1002 +8888 +14001 +19777 +1742 +7191 +6492 +17321 +2068 +991 +15616 +18921 +2856 +8685 +8401 +19251 +7252 +16467 +4786 +1337 +7162 +12561 +660 +18128 +16329 +15805 +8765 +8106 +13931 +4253 +1899 +8547 +9874 +10070 +19855 +7469 +9369 +10993 +18299 +14560 +421 +11541 +17590 +11107 +17359 +8500 +18818 +17552 +3470 +8992 +2177 +9326 +16060 +1450 +8070 +6250 +9581 +5212 +12286 +10537 +16717 +17325 +16510 +11787 +9036 +16108 +16005 +15393 +15649 +12496 +1824 +561 +10873 +19807 +1411 +6834 +19425 +4272 +7146 +9611 +18896 +18294 +17823 +4757 +14002 +2660 +3994 +14277 +969 +5206 +6735 +16567 +4575 +13624 +9110 +798 +15233 +15876 +13539 +16505 +15269 +12232 +9980 +15998 +7732 +14228 +14795 +3918 +11534 +7952 +11627 +16205 +16946 +17793 +9019 +3471 +1285 +239 +17953 +15475 +5977 +12189 +13401 +10815 +6292 +19903 +7327 +6760 +6556 +16262 +12474 +3330 +12228 +2534 +19901 +5445 +6362 +3049 +1628 +6325 +16137 +15806 +3920 +19692 +1698 +8638 +10448 +7519 +2776 +2619 +13450 +19679 +12958 +18504 +7800 +15653 +19708 +13496 +11813 +3969 +1617 +5836 +14118 +3660 +3449 +959 +17861 +17043 +16370 +3242 +16253 +11202 +17489 +5862 +1627 +18955 +19988 +1843 +7603 +2440 +15520 +11045 +7795 +19496 +9489 +9346 +6272 +11126 +18224 +1203 +18554 +11653 +18772 +16097 +9587 +7388 +8880 +19014 +543 +14562 +12990 +3748 +5647 +8797 +14232 +11971 +19479 +7610 +10091 +1271 +7820 +1673 +17328 +2594 +7343 +11236 +874 +3089 +7018 +16476 +2543 +6482 +17442 +67 +8750 +16804 +12381 +5006 +10131 +14996 +19473 +8490 +2193 +16635 +1165 +7183 +814 +17197 +6759 +6047 +10512 +2091 +9638 +204 +12493 +4565 +15707 +8232 +6329 +12355 +5023 +17163 +729 +11060 +6342 +14723 +11649 +16541 +15807 +10782 +8629 +6041 +11896 +8801 +17349 +10470 +9858 +14075 +14626 +19697 +6045 +6171 +9956 +49 +12119 +3902 +14407 +15065 +15294 +6202 +11537 +16072 +17906 +2861 +7833 +16529 +7693 +8692 +614 +8952 +17057 +17227 +4899 +4345 +6184 +16556 +12150 +6706 +17543 +19292 +18274 +10212 +15172 +18316 +3349 +6396 +2695 +1666 +4209 +18277 +14509 +7526 +14587 +13711 +2701 +11318 +7359 +7451 +14937 +2357 +12236 +9354 +4396 +15724 +774 +9248 +8741 +13075 +13720 +1303 +8266 +297 +12084 +10243 +16373 +17437 +4478 +1064 +15761 +8887 +3265 +7413 +14851 +18791 +16852 +667 +6673 +251 +16703 +16756 +5197 +8570 +18065 +13676 +11280 +7581 +14199 +1681 +1094 +10998 +14419 +15655 +3625 +2520 +13185 +7110 +15500 +6580 +8159 +3202 +14387 +10684 +19307 +5348 +14265 +13122 +11848 +1550 +12552 +8395 +6506 +17169 +14684 +7286 +12039 +1476 +5620 +8775 +14177 +19511 +1005 +15419 +1601 +1675 +17138 +9162 +9172 +10298 +7258 +16748 +12974 +7620 +3694 +16357 +7943 +11426 +5682 +6565 +10333 +15589 +12567 +2227 +9777 +18432 +613 +839 +13344 +12205 +7941 +19245 +14968 +15595 +19147 +11613 +1695 +7502 +13653 +16324 +803 +4036 +14420 +2923 +18862 +11313 +10819 +8182 +15715 +6773 +12703 +6414 +17412 +2858 +17174 +7742 +9877 +11493 +38 +15556 +16962 +2829 +6205 +11902 +396 +11129 +5880 +14792 +12441 +17998 +69 +13664 +11580 +6084 +3525 +9990 +7069 +12692 +11726 +6145 +16715 +10095 +4293 +8728 +2823 +19998 +11276 +11329 +17646 +8009 +35 +5078 +10708 +7392 +11222 +4618 +12078 +1442 +14970 +15156 +6881 +3971 +2911 +7753 +4560 +14590 +4355 +10084 +6390 +8986 +7987 +7601 +2294 +17913 +7088 +15866 +15701 +5670 +14004 +8526 +17111 +14183 +14182 +6203 +18037 +4071 +18852 +10211 +7609 +15179 +15823 +10365 +13672 +19276 +15221 +11722 +6340 +16977 +9780 +14231 +11031 +719 +9797 +10705 +6775 +15435 +2592 +5224 +11256 +1386 +15251 +3125 +441 +6043 +16791 +19722 +16489 +15714 +2712 +7068 +4070 +16193 +7334 +8960 +1948 +9576 +13483 +11828 +18934 +7745 +13740 +16678 +718 +19145 +9998 +18233 +15327 +13971 +2756 +9602 +11095 +16348 +97 +10999 +8721 +13599 +4590 +11814 +8074 +16174 +8943 +12654 +12045 +15975 +3539 +10518 +15246 +15548 +14337 +16401 +468 +17409 +11063 +3783 +13608 +4621 +1536 +18990 +4994 +8020 +2780 +638 +11465 +14086 +4173 +14497 +6868 +316 +2151 +3672 +6934 +12739 +1026 +17584 +15290 +18151 +12861 +8203 +17444 +18532 +17967 +15313 +16661 +15814 +14410 +9567 +8268 +1418 +16936 +17695 +14013 +5707 +15870 +16975 +17117 +11635 +18866 +16530 +10301 +16424 +9982 +2076 +19111 +1867 +9856 +8551 +13097 +1984 +11011 +10725 +16015 +371 +17 +2327 +5102 +13302 +9442 +13025 +5669 +4622 +1660 +7876 +18531 +6832 +13570 +11001 +8166 +15467 +16666 +1251 +13377 +5770 +7265 +3851 +726 +18150 +18646 +10270 +3239 +871 +7779 +141 +11644 +879 +18105 +14687 +17158 +18605 +3895 +5298 +5081 +3272 +16441 +7632 +7404 +18597 +8138 +5721 +10678 +8186 +17795 +140 +16811 +3569 +6559 +5141 +7292 +15254 +325 +12348 +11977 +9511 +13403 +14563 +8578 +8341 +18473 +5754 +4098 +19989 +9179 +5426 +8502 +7425 +2617 +9323 +8332 +13509 +3338 +9921 +16739 +3402 +6214 +15692 +17999 +14914 +18267 +4713 +8558 +6464 +17779 +15722 +5367 +15661 +3244 +12322 +4212 +6552 +6885 +14614 +15927 +218 +14159 +10385 +12655 +10478 +1455 +16632 +8738 +19565 +1549 +14692 +17387 +17918 +17168 +4199 +19484 +16932 +5324 +5631 +4647 +10460 +10110 +17033 +13275 +12807 +19811 +5860 +2595 +16139 +10339 +11386 +17716 +15566 +822 +8953 +19795 +14760 +9985 +15775 +3328 +7022 +5666 +15704 +19926 +12575 +16347 +1313 +9941 +2840 +15093 +14148 +13627 +14344 +11941 +19970 +269 +1318 +14241 +3019 +8419 +19940 +10171 +4662 +5194 +4841 +4117 +14623 +19575 +14416 +824 +938 +7891 +6103 +15516 +10614 +5925 +16818 +18166 +13515 +95 +15406 +19134 +11628 +17979 +1319 +2744 +5070 +18099 +2359 +16881 +7317 +10696 +7630 +13391 +15771 +7346 +18313 +8844 +16699 +12388 +19591 +6455 +14269 +1646 +11540 +8579 +12195 +6517 +10214 +3041 +4329 +16465 +14135 +2266 +8262 +7932 +16970 +7365 +15173 +16220 +18402 +18717 +8235 +12535 +15352 +3006 +14791 +3232 +18218 +15011 +17642 +3547 +753 +5095 +17252 +3986 +3626 +4497 +1981 +9866 +1851 +2915 +633 +3008 +19073 +1672 +16067 +1304 +2770 +17594 +10531 +1316 +3147 +17340 +8314 +4191 +5851 +19306 +12734 +9571 +7472 +1162 +762 +12501 +14104 +3462 +12118 +19537 +10867 +16985 +17121 +10331 +7207 +19291 +14819 +19171 +16103 +1810 +11822 +10167 +5644 +2750 +11956 +2638 +13430 +8726 +15164 +16921 +14834 +3228 +13214 +12320 +9083 +7657 +9446 +14592 +14480 +11566 +17878 +625 +1444 +19721 +16743 +17076 +2512 +19734 +5115 +8468 +16031 +6970 +12674 +17941 +12439 +16286 +15833 +611 +8489 +15367 +1186 +12645 +19794 +12851 +15045 +5815 +13926 +7450 +5447 +5587 +10840 +1473 +19572 +10193 +4492 +1052 +13756 +13386 +14158 +15816 +17053 +19329 +19381 +4953 +8058 +4528 +12776 +18810 +2164 +9786 +16531 +7587 +17128 +6062 +15194 +8386 +15312 +4862 +10516 +18457 +15501 +8014 +5049 +18686 +9979 +13290 +15217 +8258 +11885 +4992 +4804 +1051 +6808 +8996 +11544 +11998 +15433 +2593 +3503 +4553 +11775 +11830 +11155 +19097 +2350 +16824 +3867 +16311 +4512 +886 +9208 +17629 +15605 +10366 +15288 +1553 +14342 +5401 +7079 +4521 +17777 +13521 +11149 +10379 +18112 +11283 +19934 +11485 +11910 +14617 +14283 +514 +19618 +13292 +9308 +19877 +1636 +17647 +13923 +370 +14766 +15962 +10177 +9713 +18321 +14160 +6218 +13667 +5873 +8849 +10158 +7221 +6839 +11160 +11390 +147 +5220 +6953 +934 +13510 +15121 +15338 +1278 +1170 +7464 +2101 +11571 +9134 +7423 +6336 +15471 +17458 +7918 +3378 +7319 +19483 +8734 +9613 +2720 +11265 +6765 +8372 +16232 +10871 +8774 +19504 +6028 +1021 +11576 +1953 +15631 +5944 +12261 +612 +6211 +3979 +2476 +10484 +9700 +12035 +6418 +4433 +12461 +1613 +9820 +10101 +13982 +11020 +6507 +14873 +12825 +848 +2488 +15477 +17672 +6393 +11936 +13241 +7177 +18271 +16063 +5349 +378 +19032 +2933 +3890 +15297 +14979 +1748 +1585 +19406 +16633 +9888 +14586 +8125 +5082 +12337 +16759 +19325 +7031 +19274 +17178 +16104 +12095 +11438 +9745 +3021 +19471 +6770 +685 +11585 +14793 +18847 +6305 +2910 +14485 +15512 +4915 +2846 +19600 +19826 +17586 +7415 +17362 +19755 +15594 +11122 +8146 +12596 +19407 +14661 +18918 +740 +10393 +10191 +8210 +19827 +13785 +5128 +8170 +12032 +11174 +18322 +10912 +9443 +9480 +17635 +11351 +17084 +1498 +19752 +6420 +16387 +2785 +10149 +9115 +16305 +15375 +5907 +16639 +11511 +12763 +14669 +19299 +18490 +18933 +6629 +16839 +13719 +15680 +7349 +17553 +14295 +18195 +18256 +10788 +9975 +6476 +10935 +10392 +389 +3844 +19319 +17549 +1842 +10006 +10265 +6475 +9405 +11574 +14731 +8437 +669 +2441 +8966 +7289 +17410 +1950 +4738 +12818 +4793 +15009 +9634 +4324 +18380 +9530 +9671 +17036 +6731 +13583 +7000 +9502 +12830 +2057 +15810 +19666 +2205 +4409 +18016 +410 +5606 +5739 +13569 +4962 +18270 +5416 +6407 +13061 +9050 +1272 +8997 +13365 +5845 +13713 +14425 +2265 +10491 +592 +18033 +6223 +16491 +15591 +738 +5190 +826 +5386 +2798 +293 +19242 +14475 +6215 +10246 +9257 +6672 +7032 +11375 +17202 +11877 +4074 +9239 +14305 +13632 +14683 +5833 +505 +3046 +14960 +11614 +3942 +14130 +5686 +16352 +10081 +8296 +13752 +8627 +1530 +338 +448 +13840 +18948 +8403 +9402 +5948 +19030 +4638 +176 +2649 +15559 +1741 +8406 +3346 +6269 +15673 +10151 +5292 +1710 +11436 +10951 +978 +12139 +6625 +1317 +8876 +5074 +16409 +4326 +3646 +2822 +10979 +11204 +4072 +3444 +16458 +4057 +16554 +1263 +3146 +5159 +15116 +6853 +2358 +18281 +8954 +1703 +3167 +8099 +12532 +7680 +19549 +5730 +6675 +10926 +13175 +915 +2866 +17992 +3420 +9885 +8557 +4295 +2335 +9846 +11275 +9523 +11905 +19419 +15062 +8896 +10465 +7295 +15543 +13428 +4676 +19146 +10621 +8863 +15911 +17798 +18672 +10390 +3336 +7783 +18747 +12730 +5523 +13064 +11019 +6104 +2153 +12998 +19804 +8382 +11757 +7257 +1593 +7521 +3356 +18181 +17710 +2027 +6584 +16875 +16215 +8757 +14496 +15645 +9207 +13318 +10850 +10286 +654 +6096 +16083 +6467 +17575 +4066 +16453 +9550 +6660 +7766 +19152 +18049 +10443 +41 +13514 +16334 +7436 +12473 +16583 +14053 +14297 +15656 +12490 +6886 +19208 +10432 +6377 +18863 +256 +10634 +2990 +7431 +19759 +6002 +2585 +9536 +3886 +6257 +16525 +15323 +1707 +16165 +15648 +5876 +1048 +4265 +15344 +307 +17066 +5471 +7759 +19561 +8494 +11599 +13033 +14924 +13999 +3749 +12344 +4163 +19128 +19181 +3887 +2925 +12744 +12087 +17291 +11311 +3662 +17814 +10228 +19105 +18335 +19362 +5667 +18221 +17856 +9600 +6035 +5779 +17796 +11086 +15926 +3731 +1908 +16463 +320 +3222 +1451 +14375 +14012 +939 +11594 +9718 +11737 +15853 +14296 +13639 +14856 +9824 +507 +4520 +15803 +16938 +15506 +16470 +11068 +17334 +585 +8791 +7489 +19713 +12283 +7707 +3277 +2922 +10703 +13287 +18629 +4452 +15291 +18096 +5059 +9210 +14525 +11264 +4363 +15985 +7696 +7087 +3120 +1823 +11117 +14340 +16978 +2399 +13609 +7387 +1223 +10276 +3259 +628 +10430 +13209 +1452 +14247 +5018 +7081 +1868 +14663 +11959 +3143 +1219 +9732 +14714 +13594 +1358 +17261 +12848 +9178 +3235 +7091 +4715 +16349 +3386 +4183 +2654 +15049 +11768 +6525 +1254 +19219 +17371 +2554 +19981 +14935 +19342 +3506 +1253 +6705 +5429 +12177 +8613 +16303 +15514 +1978 +4585 +8365 +10140 +11950 +10947 +10651 +16127 +104 +16307 +1472 +10463 +12915 +1869 +17835 +8275 +10313 +11693 +18844 +14498 +12745 +16452 +13059 +19867 +16929 +5899 +1169 +5028 +6875 +6076 +3645 +11112 +12965 +7086 +13105 +11584 +19634 +14686 +7704 +16408 +16825 +14870 +13901 +11735 +10240 +4206 +4372 +6818 +6966 +7073 +8078 +503 +10373 +19271 +7351 +1416 +9702 +14438 +4273 +16421 +10187 +17427 +17797 +19366 +2521 +19397 +12893 +18562 +14896 +7338 +17932 +14203 +5328 +14418 +1519 +1737 +13480 +16145 +9785 +8458 +14726 +6824 +3310 +5844 +16095 +6259 +7621 +407 +12332 +1768 +14428 +2949 +12868 +2459 +9959 +4235 +2453 +15633 +18381 +18265 +10798 +19553 +6570 +19683 +13912 +4956 +16701 +7492 +3388 +8057 +7060 +16726 +9445 +5902 +9935 +17300 +6714 +86 +9015 +6465 +12651 +13030 +6620 +7225 +10315 +7121 +9095 +13362 +14194 +16129 +5679 +13769 +5767 +13162 +14483 +5204 +1019 +3174 +1449 +2905 +6050 +16589 +17834 +13582 +6598 +12528 +6971 +13350 +6102 +16308 +17064 +12426 +10974 +8112 +1864 +5856 +10451 +17559 +12475 +10499 +8163 +13683 +3580 +7045 +18352 +7551 +3700 +10320 +12245 +10160 +9726 +14578 +2031 +5491 +10494 +15716 +15909 +9305 +4371 +1955 +2396 +14843 +607 +19224 +12076 +11346 +13781 +2080 +19571 +1340 +7270 +10090 +15693 +6521 +2337 +10535 +15053 +12504 +7303 +3973 +10345 +18965 +1756 +2566 +2982 +695 +11573 +12760 +19702 +17811 +18104 +11103 +8990 +3733 +13172 +3842 +7247 +16693 +19401 +432 +15256 +15841 +6010 +11327 +1286 +10485 +1971 +1866 +9683 +13271 +14751 +5999 +2766 +5272 +7797 +8620 +2299 +11316 +11133 +5782 +14115 +6175 +7272 +5107 +2945 +16915 +18776 +11021 +13335 +5957 +14566 +15760 +3989 +3800 +7457 +4890 +11228 +2531 +686 +6115 +15981 +14391 +13766 +17630 +17154 +9555 +13019 +10872 +11234 +5340 +1863 +1370 +14740 +4696 +5940 +16460 +13689 +16637 +8303 +12407 +5600 +9533 +19776 +18427 +17960 +4938 +10310 +4055 +12240 +11317 +548 +12440 +11530 +3898 +1574 +9605 +6099 +7442 +13387 +16315 +5396 +17035 +17877 +15302 +7410 +10299 +17225 +16548 +10487 +5377 +19773 +8735 +6194 +11480 +17802 +10625 +7793 +5671 +13685 +15966 +6278 +4336 +455 +15178 +11860 +16209 +7867 +8376 +3062 +12403 +12938 +8787 +17420 +9419 +4813 +5622 +13646 +10469 +2914 +8238 +5269 +13951 +6064 +6140 +18419 +11691 +14216 +14502 +15767 +16925 +10567 +6489 +14825 +2124 +11036 +19312 +6526 +1417 +19688 +15686 +1945 +8192 +250 +11190 +133 +14045 +1532 +8040 +6543 +9400 +3492 +19554 +2147 +19503 +13124 +3688 +4002 +14845 +8580 +18435 +14868 +5075 +15577 +354 +19876 +19144 +11075 +10962 +6633 +16722 +14885 +14299 +11838 +13305 +12772 +3932 +14951 +17939 +3031 +7323 +6950 +852 +13363 +14899 +2280 +16826 +3702 +18951 +1091 +6722 +11533 +13493 +10468 +11598 +12737 +6310 +577 +14609 +5214 +1762 +17122 +11048 +13327 +8569 +18535 +19894 +6281 +9934 +2634 +14894 +10866 +3475 +4038 +9783 +1273 +17957 +14467 +14236 +13904 +14214 +14541 +2074 +12175 +12103 +15535 +4486 +4398 +2964 +1949 +10382 +4874 +7688 +15407 +13482 +17181 +11261 +13127 +19277 +2023 +6077 +7275 +9377 +8527 +15550 +1333 +5219 +9526 +12349 +8185 +16890 +1711 +15551 +15787 +3093 +14372 +14809 +12968 +10799 +2962 +17273 +13548 +8261 +10261 +11642 +622 +1904 +2162 +17288 +15265 +17126 +12512 +5824 +11646 +11960 +17214 +19724 +9793 +14379 +2120 +16520 +16141 +8193 +12282 +15688 +10020 +4837 +7787 +10477 +15160 +10748 +705 +400 +460 +16391 +15749 +19480 +12273 +17088 +14699 +18840 +14936 +14023 +7279 +10559 +5689 +2224 +1153 +7903 +3552 +16959 +17667 +17120 +18425 +11482 +18264 +15253 +1657 +7214 +14136 +11004 +8188 +16316 +9540 +3864 +18474 +162 +18604 +902 +12929 +4256 +8560 +1027 +8281 +11085 +7595 +5993 +7698 +15978 +19090 +3045 +4970 +16614 +9643 +9131 +12238 +19655 +10226 +15959 +8282 +11286 +2984 +11394 +2133 +19586 +761 +4551 +18276 +13194 +7337 +14770 +19065 +15191 +17765 +18905 +11882 +12131 +10882 +18656 +19550 +596 +9725 +13297 +3693 +2428 +16485 +9569 +4201 +5363 +725 +5273 +17098 +8931 +362 +10770 +10340 +1940 +3013 +6516 +10542 +3308 +16371 +18478 +9044 +2307 +284 +1888 +2325 +18719 +9845 +423 +5781 +3273 +1467 +11749 +9641 +626 +7718 +13674 +10922 +15280 +6896 +7379 +10062 +9297 +17937 +11474 +9111 +4461 +19049 +8298 +14370 +1947 +5145 +18411 +19017 +12477 +11189 +16061 +1060 +15899 +5859 +19452 +16459 +11762 +742 +10520 +11469 +19933 +15974 +7395 +8820 +6119 +14287 +19360 +3181 +12085 +3968 +941 +11968 +11166 +1097 +18215 +14204 +16455 +2732 +13499 +6439 +1376 +18674 +14211 +13531 +2935 +4308 +791 +10316 +2696 +19330 +2037 +5054 +1723 +17714 +5760 +11347 +7117 +17910 +19498 +2365 +16898 +7394 +8668 +16335 +14940 +2094 +6481 +14309 +7661 +3493 +2715 +18742 +13598 +12327 +13445 +12533 +3927 +5610 +15112 +3957 +249 +4463 +16670 +776 +9071 +1894 +4716 +16708 +11464 +10753 +1725 +11680 +2220 +16285 +14743 +10295 +12075 +17333 +15529 +16010 +1641 +18549 +10728 +8515 +17018 +9765 +18745 +1754 +2877 +13622 +3889 +1753 +5032 +6425 +3998 +13268 +18086 +6124 +9672 +10994 +12976 +1493 +8039 +6802 +312 +11252 +18244 +19843 +18273 +17254 +7764 +2940 +16572 +8587 +11556 +18522 +3419 +11039 +14084 +3649 +15987 +7172 +14810 +7016 +17060 +13877 +1871 +11376 +5176 +4584 +12354 +10178 +18832 +18569 +14443 +219 +2150 +18328 +2311 +2370 +5488 +17743 +1970 +7738 +15562 +3845 +1146 +1100 +916 +1308 +1537 +19514 +9833 +3848 +16558 +8033 +1404 +6013 +6291 +1378 +19580 +7096 +17146 +3862 +17870 +846 +12736 +2855 +10034 +15604 +9230 +15270 +101 +440 +723 +2615 +13576 +3211 +19581 +17771 +11631 +3647 +1835 +8641 +4827 +8098 +13977 +10411 +17632 +16948 +2608 +373 +2233 +8980 +18729 +9277 +14417 +5691 +14108 +15746 +11056 +16425 +6320 +13618 +15906 +11572 +4595 +8773 +13120 +964 +15387 +15092 +9421 +7151 +17886 +4730 +16956 +16296 +3434 +10851 +9667 +4573 +10449 +6927 +16545 +12056 +11187 +892 +6889 +3017 +14949 +10702 +563 +17595 +17625 +12779 +713 +5529 +15189 +9512 +10591 +7277 +19636 +5160 +17784 +13013 +2258 +9892 +15846 +1049 +16321 +18912 +18534 +2541 +14494 +7645 +739 +593 +7652 +14119 +706 +4843 +248 +4645 +14126 +16547 +11262 +14393 +3967 +10667 +6900 +10923 +7138 +1350 +4868 +313 +19297 +18600 +11524 +4810 +5183 +11776 +2438 +2011 +15691 +6454 +1059 +13072 +1092 +6315 +16500 +17965 +6113 +12995 +17171 +19764 +14942 +2058 +16433 +2709 +159 +7077 +9580 +16157 +7733 +1964 +9762 +18158 +16611 +19454 +17005 +16738 +4569 +17220 +17232 +2063 +10749 +7924 +3763 +7563 +5801 +11663 +2951 +2760 +9996 +16059 +11545 +14519 +14320 +14530 +16587 +9330 +13952 +7913 +9424 +3939 +12379 +2805 +19612 +14863 +6327 +4216 +8927 +3457 +4161 +5192 +6276 +11930 +13811 +4947 +1551 +11051 +12770 +2603 +1568 +10025 +9815 +12170 +10886 +14733 +6125 +16147 +7647 +2089 +127 +5617 +4269 +9869 +211 +8821 +7182 +773 +3282 +2024 +18935 +18489 +9693 +12551 +2510 +4368 +15201 +11091 +13418 +8794 +16934 +8565 +7115 +14739 +12751 +9292 +11110 +797 +8362 +18954 +9219 +1305 +3852 +13234 +7947 +15610 +17274 +8364 +17507 +3799 +19316 +629 +5821 +5380 +9772 +8680 +2069 +9957 +19628 +14470 +1490 +6322 +9217 +10894 +15912 +19072 +7546 +18711 +9351 +17344 +16406 +6415 +3959 +11623 +9160 +16294 +7222 +10098 +18890 +19443 +734 +14258 +15864 +18055 +18246 +6952 +6609 +8740 +16001 +9927 +6227 +11079 +8645 +2831 +11816 +14363 +13110 +7886 +4339 +13742 +10878 +3590 +4367 +18580 +18164 +15478 +8747 +8293 +3047 +17462 +12161 +15668 +11724 +10645 +1356 +17465 +11186 +3727 +17337 +659 +2360 +17991 +19640 +18114 +4882 +8533 +10305 +10492 +1688 +3665 +10652 +19392 +11198 +10619 +8539 +6588 +202 +17699 +10700 +12293 +18008 +1095 +1288 +7094 +6729 +5572 +16779 +10148 +10890 +15373 +9518 +17190 +18618 +4302 +15469 +11796 +5261 +122 +17466 +19447 +3274 +9795 +11991 +9519 +5778 +9665 +1635 +18131 +15427 +17103 +8905 +18095 +11588 +261 +7822 +62 +11419 +10227 +10517 +7116 +16457 +16965 +18396 +8595 +15547 +3528 +7210 +9254 +11244 +11212 +19311 +4615 +8425 +18269 +18696 +13793 +5586 +13113 +5564 +17045 +2481 +6008 +2795 +4734 +18793 +17000 +1816 +10467 +9492 +15747 +3426 +9901 +17713 +18100 +17977 +18676 +4190 +6447 +7129 +19236 +3460 +7909 +4431 +19501 +18626 +5369 +12849 +6301 +10500 +4374 +4567 +17293 +6733 +2963 +17132 +605 +8854 +12211 +4789 +13052 +10774 +2017 +8015 +2614 +5858 +235 +12576 +14343 +4922 +10671 +11567 +15774 +14374 +4541 +19063 +19127 +7798 +8865 +12836 +2487 +7329 +1374 +17585 +15231 +7887 +178 +9238 +4853 +11334 +5582 +3938 +2466 +4554 +16792 +13012 +6969 +8270 +19735 +3772 +73 +5399 +12822 +2969 +2449 +11242 +16487 +10213 +2400 +16873 +16410 +858 +18653 +5307 +17497 +185 +13165 +6163 +4049 +13697 +3059 +4869 +1807 +17432 +16156 +10456 +17152 +12289 +2602 +8389 +19662 +15718 +5722 +11290 +10880 +9857 +887 +18643 +8479 +19928 +8683 +12984 +5602 +8661 +10905 +10283 +6754 +169 +14716 +9011 +8027 +14197 +6600 +14988 +12833 +14043 +14173 +4865 +15399 +16534 +18426 +18932 +7367 +8195 +19627 +3233 +11855 +10906 +1306 +3002 +12252 +15698 +3686 +8691 +7433 +6355 +515 +15365 +15792 +6835 +12959 +2492 +12167 +13079 +15476 +4448 +5609 +14565 +4766 +19833 +10251 +7996 +12524 +1900 +11099 +19864 +10577 +17485 +13293 +5513 +7649 +1258 +9091 +16369 +19542 +16597 +18165 +6074 +1919 +15933 +5830 +9029 +6037 +16183 +11732 +19318 +15450 +15849 +13164 +19983 +16278 +15728 +3899 +3546 +13134 +9193 +823 +5110 +2705 +17755 +17570 +17742 +324 +8350 +18757 +1701 +16686 +280 +5384 +18751 +14360 +4879 +12368 +1406 +15391 +16833 +18391 +11402 +5553 +12571 +19140 +6217 +12347 +17947 +19528 +17166 +2974 +18291 +6809 +6669 +17279 +19214 +3588 +16084 +9191 +495 +11090 +14771 +9669 +5983 +12523 +936 +10085 +4671 +16565 +18606 +9997 +3237 +4035 +14838 +14312 +19151 +10384 +3448 +2451 +17883 +15967 +11651 +17093 +10507 +19902 +10324 +17904 +19882 +19900 +14545 +9190 +3769 +12907 +1746 +3257 +11883 +6231 +11105 +8805 +8336 +5755 +645 +19052 +14412 +17748 +6387 +12985 +1393 +6764 +3877 +9361 +11440 +12346 +675 +12017 +4707 +13942 +10989 +10650 +12102 +11636 +14206 +19305 +2727 +15731 +9468 +6149 +14234 +12074 +16152 +7915 +5151 +12725 +8674 +4204 +19991 +13550 +14573 +17671 +17651 +27 +2640 +3554 +3361 +19783 +66 +2573 +12249 +14556 +5008 +61 +4264 +8263 +18409 +80 +6667 +3530 +9801 +7316 +7517 +17828 +52 +952 +5209 +5982 +3830 +7134 +15370 +11547 +13602 +6708 +16806 +19590 +5301 +5633 +8908 +9950 +841 +16730 +2109 +6060 +6915 +8353 +13086 +9952 +9301 +9449 +12165 +13024 +946 +19044 +30 +12837 +4968 +7857 +15117 +9839 +12898 +13051 +1341 +4535 +4982 +8334 +14171 +4635 +8435 +14079 +17272 +5774 +11843 +7989 +17933 +5953 +3467 +7520 +16231 +11182 +15613 +2789 +15163 +12458 +19614 +17393 +6277 +10314 +2354 +14161 +2824 +11909 +4770 +15581 +18891 +4826 +13497 +12040 +3540 +5560 +4277 +16318 +6738 +19472 +19344 +1475 +1705 +7973 +12852 +9735 +9016 +9592 +4391 +19209 +961 +7515 +14681 +7568 +2864 +17477 +8571 +9121 +3401 +14306 +8461 +14476 +10724 +4705 +15333 +4039 +1465 +2477 +2183 +17209 +18621 +17140 +8833 +18347 +19269 +17183 +19213 +13603 +18152 +6595 +15114 +11868 +17711 +2533 +591 +16742 +4052 +16053 +700 +8729 +3256 +19633 +18336 +8724 +6702 +1671 +19818 +382 +16 +16447 +5683 +5248 +4749 +6758 +11708 +752 +12797 +1494 +4703 +5157 +183 +19955 +12015 +9076 +15188 +15625 +19415 +7757 +11507 +15700 +19069 +18963 +14164 +11888 +19283 +17157 +394 +14840 +14513 +464 +11163 +15624 +4739 +18529 +12859 +2955 +3135 +3061 +4931 +6718 +10241 +17568 +17791 +19036 +4180 +11739 +15131 +14618 +17382 +242 +13273 +19837 +12625 +10363 +1344 +18788 +19028 +9907 +9261 +6656 +5113 +8095 +391 +3337 +16601 +1735 +6685 +10663 +913 +1721 +18056 +6468 +17737 +3098 +7917 +15449 +14897 +2475 +10296 +7658 +9244 +7393 +5544 +9486 +18857 +1685 +19229 +2170 +14208 +10582 +3690 +1221 +10675 +2753 +9972 +8881 +6155 +19762 +4474 +8736 +16992 +19671 +19979 +19110 +17617 +18592 +6479 +14134 +8375 +18015 +14678 +1071 +4820 +14020 +11147 +878 +10569 +6830 +6891 +439 +3795 +9936 +13331 +17982 +381 +3507 +6031 +12832 +15267 +6461 +6522 +2719 +8568 +3285 +4905 +15241 +1173 +11857 +10741 +15871 +5812 +4217 +15939 +11997 +273 +9654 +15536 +16036 +15105 +15708 +4665 +13862 +2954 +6634 +13320 +9861 +8301 +14575 +6778 +9339 +11272 +4880 +12945 +18349 +12218 +18024 +3129 +17170 +18168 +17759 +1360 +9435 +15989 +3431 +6851 +14891 +14738 +7321 +9336 +4558 +9461 +3548 +10630 +16000 +10483 +9918 +19210 +19569 +19896 +11083 +18936 +7653 +14225 +1514 +19748 +9034 +15258 +1516 +3770 +12785 +3781 +11315 +12424 +6892 +10414 +12314 +3157 +5096 +9166 +15303 +2189 +8838 +18492 +2680 +6426 +10697 +12333 +1503 +10769 +4426 +1744 +1667 +9736 +13034 +3518 +14252 +39 +19635 +7834 +19081 +8712 +6510 +2262 +18516 +16549 +18310 +1487 +6143 +3010 +8938 +8199 +19665 +17116 +12405 +9583 +9768 +14913 +7445 +7284 +1648 +17852 +16507 +19845 +8220 +7633 +11504 +16816 +12246 +9138 +19042 +2111 +2103 +8101 +4376 +19343 +17733 +9891 +11721 +14944 +13011 +7233 +13709 +7497 +8891 +18775 +10374 +9212 +9214 +18577 +8814 +11918 +3865 +3897 +8919 +18946 +18640 +12360 +17318 +8739 +383 +16762 +3873 +18292 +7537 +8677 +15824 +18232 +3194 +5787 +12028 +15332 +290 +12153 +1439 +5179 +16210 +19941 +13131 +11859 +11461 +17375 +14773 +146 +17014 +15061 +33 +9267 +16428 +9417 +12916 +9472 +1670 +19143 +16099 +5207 +8894 +11279 +16501 +361 +17180 +2569 +18449 +19718 +500 +19966 +3750 +4579 +16723 +8076 +4322 +18058 +17470 +4795 +13477 +5350 +6955 +5634 +14198 +3537 +13970 +17670 +6253 +15321 +10971 +328 +13640 +18502 +17659 +17541 +8991 +5567 +2298 +11490 +12821 +12527 +1208 +4152 +8764 +19745 +10821 +12727 +5492 +7025 +4223 +6156 +2073 +2799 +12353 +15820 +11932 +9629 +28 +8407 +9738 +11246 +13471 +12611 +11138 +6945 +6367 +7170 +7942 +13479 +4743 +8982 +8853 +6547 +12207 +19828 +3952 +8217 +538 +16993 +10727 +19123 +19118 +18574 +19974 +16464 +13631 +16828 +206 +13190 +11750 +658 +7879 +10083 +15459 +17922 +1443 +17613 +18045 +3329 +2714 +2587 +11538 +153 +10941 +11061 +2827 +2841 +15304 +13414 +3825 +4737 +1070 +4366 +15585 +7775 +2006 +19929 +1458 +7208 +15862 +9717 +7930 +10688 +18001 +9434 +4298 +1216 +7871 +15060 +15934 +9575 +12632 +549 +3870 +16910 +5007 +7226 +7174 +9203 +139 +4623 +12201 +15495 +18009 +3487 +8800 +13607 +4725 +1879 +8289 +10371 +19138 +16200 +3373 +6998 +16566 +15488 +837 +14529 +18170 +4815 +8308 +4611 +9564 +11694 +9410 +15106 +4664 +10041 +1510 +10835 +11841 +19533 +18327 +13441 +10486 +91 +4405 +9995 +1343 +17137 +13673 +19595 +10005 +14806 +18703 +14991 +17962 +3464 +11582 +13716 +14196 +7741 +8581 +1460 +18501 +5019 +10733 +1780 +4934 +9157 +19518 +7796 +15493 +13257 +10092 +1524 +9415 +7140 +18177 +8151 +4263 +7494 +3088 +10876 +19832 +16850 +6829 +2498 +18806 +4042 +15615 +19469 +4858 +18851 +13180 +11382 +13199 +533 +1464 +17678 +8929 +12911 +8209 +13900 +8388 +950 +11406 +11319 +1895 +9430 +199 +7061 +11799 +9794 +19258 +11861 +4923 +13227 +12434 +18900 +13917 +7992 +9379 +18004 +9398 +15494 +13617 +13277 +8486 +2229 +6800 +17394 +7196 +132 +17662 +8066 +11308 +18061 +7760 +2653 +19492 +4476 +11177 +17404 +1649 +12086 +5101 +16246 +15982 +16860 +2301 +17193 +14664 +15780 +3309 +85 +14415 +15586 +10800 +8965 +9384 +2047 +3118 +13551 +13157 +14022 +6192 +7371 +12258 +5589 +2697 +13140 +1495 +10028 +17589 +5970 +19410 +14039 +10096 +19607 +7758 +4702 +14821 +7755 +15005 +11592 +16602 +5062 +6178 +15634 +8306 +5969 +9557 +6840 +11698 +2913 +6519 +5613 +16986 +1618 +11728 +16964 +9827 +19768 +16351 +16081 +2041 +20000 +19840 +425 +16736 +5961 +9537 +7053 +7328 +18140 +17990 +5379 +2408 +16744 +10723 +13309 +18235 +532 +19810 +10423 +149 +5716 +10557 +8693 +6640 +16555 +4974 +16798 +11157 +7332 +17008 +9126 +4525 +6186 +15576 +8913 +8659 +11829 +4365 +1107 +1802 +9291 +197 +5368 +12778 +9264 +15612 +11287 +18333 +3699 +19486 +6968 +11494 +2145 +13340 +5803 +13996 +14826 +17842 +2556 +13613 +3740 +12562 +2313 +14665 +13324 +19985 +12914 +19182 +8045 +10325 +18876 +18386 +5056 +18655 +19922 +4245 +5120 +15460 +9364 +12080 +17101 +8511 +14332 +4612 +4782 +8532 +15298 +10424 +757 +8839 +5752 +16955 +2341 +3642 +5541 +5034 +4059 +12266 +18647 +8816 +781 +13267 +12622 +10514 +18828 +3037 +14938 +1907 +187 +17248 +16877 +5664 +18680 +16663 +15362 +10546 +8207 +771 +13824 +7488 +17846 +5690 +19954 +18339 +2900 +2687 +6356 +3583 +11656 +6225 +13465 +7291 +9296 +18139 +14052 +18149 +17484 +11145 +2560 +11009 +10813 +10828 +4193 +1624 +6162 +8175 +17588 +11955 +18029 +10115 +1322 +14889 +4515 +4691 +17524 +17787 +6618 +1481 +7508 +16484 +12415 +9174 +18111 +14062 +2897 +7417 +11700 +7743 +16106 +6174 +2279 +7390 +13408 +177 +4280 +14347 +12790 +9561 +16586 +14129 +16766 +9003 +14523 +10123 +12005 +15650 +310 +9924 +19436 +10417 +15540 +75 +8871 +10116 +15314 +15818 +14055 +16217 +7665 +728 +13464 +7945 +2752 +18395 +16814 +11817 +6977 +18240 +11923 +980 +15882 +17301 +19982 +15905 +14945 +13099 +7263 +14413 +6051 +7803 +4142 +2902 +2056 +2865 +799 +11741 +15907 +587 +14784 +10686 +336 +1854 +225 +142 +3592 +13961 +10503 +10488 +19160 +12375 +911 +2009 +2042 +17563 +8723 +17424 +4129 +11951 +5546 +13500 +11456 +14142 +13666 +9418 +18587 +15896 +9082 +5196 +18320 +19615 +17551 +9064 +10565 +4500 +14585 +16436 +12483 +1840 +17899 +9362 +9265 +5914 +11898 +11167 +9854 +4034 +5603 +8410 +3760 +19308 +17423 +16598 +15754 +8761 +6956 +3490 +3789 +12964 +13390 +10810 +12432 +3838 +3940 +12895 +15567 +15108 +7453 +8940 +5738 +11901 +6198 +3397 +14695 +16878 +5909 +13232 +17926 +3679 +3238 +7424 +15736 +5806 +19995 +7589 +88 +9062 +8669 +19248 +11074 +12419 +3215 +4120 +3170 +16863 +1817 +522 +4447 +13208 +13705 +6716 +6302 +10037 +6181 +17873 +6654 +16859 +6287 +19237 +16149 +1923 +891 +12891 +18735 +9451 +15936 +9271 +2738 +4239 +18558 +18238 +15856 +19092 +14689 +17996 +6589 +9790 +3509 +1147 +11270 +15614 +5257 +1000 +16135 +6852 +1573 +584 +126 +17694 +16945 +12143 +18584 +17415 +2443 +7664 +1929 +14887 +3007 +1571 +5508 +18113 +18537 +19310 +14948 +6219 +19055 +9327 +19233 +14977 +19158 +17198 +18438 +1297 +19463 +9834 +2185 +289 +2174 +3279 +18722 +3739 +5981 +18889 +8717 +6870 +12827 +16306 +6255 +15222 +3175 +10656 +8059 +5289 +6052 +10126 +3560 +19019 +19074 +12548 +5330 +15107 +18956 +5288 +4637 +6821 +11801 +5088 +5452 +2576 +2834 +4381 +13668 +11780 +11804 +5424 +14355 +6981 +2104 +16546 +8161 +10689 +18147 +15017 +12454 +18385 +2188 +343 +4839 +18811 +14270 +2967 +8460 +4386 +9252 +16823 +11793 +10022 +10653 +19374 +8698 +457 +894 +7594 +18736 +19646 +10901 +18689 +11811 +8414 +7155 +12829 +1658 +14408 +15804 +6374 +9964 +12155 +12140 +10759 +4932 +11621 +6410 +5931 +18136 +14831 +7458 +17869 +11119 +3141 +5364 +19699 +8658 +13235 +17915 +5036 +16390 +15583 +17150 +11454 +9910 +7687 +5442 +18189 +3206 +11422 +1501 +11769 +12845 +13812 +8449 +9623 +5164 +2168 +16268 +6984 +4464 +3909 +5980 +18325 +16419 +4709 +9107 +19421 +8760 +5287 +17942 +4958 +12387 +19304 +17419 +3734 +6524 +4895 +7821 +1716 +1546 +14829 +16990 +11678 +8834 +5479 +4444 +9386 +18126 +5303 +17539 +10729 +6092 +8165 +15001 +13300 +8236 +9150 +8047 +10551 +23 +3545 +1274 +11937 +8542 +7556 +10419 +10356 +17900 +17353 +9499 +3443 +1009 +19184 +2166 +3286 +4697 +17062 +8110 +18209 +10401 +4301 +1332 +10394 +6138 +12113 +15988 +518 +8851 +5053 +17620 +8265 +14409 +3035 +6495 +9881 +10823 +11887 +16272 +12427 +7411 +16009 +11610 +1774 +19133 +16576 +7034 +12846 +491 +3263 +10455 +12707 +6398 +18204 +11277 +18709 +7026 +1548 +1872 +4779 +10606 +10162 +14620 +9721 +11912 +2666 +9061 +15600 +13962 +3960 +17738 +10266 +18363 +296 +15379 +14978 +5068 +19585 +5063 +15742 +7960 +9703 +18496 +16483 +6962 +16024 +5847 +18880 +17082 +16627 +1158 +8713 +6611 +10861 +8002 +14392 +13153 +2005 +9893 +9373 +2981 +2404 +14315 +10758 +12193 +19139 +1109 +7555 +12242 +10900 +19676 +5433 +17606 +12966 +13381 +11096 +11559 +7201 +11098 +6936 +9796 +1639 +3491 +4075 +1847 +13108 +12556 +1138 +19437 +5810 +10578 +8128 +11076 +356 +14980 +16203 +17092 +6511 +11810 +2248 +7762 +2859 +19566 +15143 +16479 +7911 +334 +15087 +15355 +7859 +19225 +4031 +10309 +1850 +14217 +15213 +12197 +15837 +6239 +9542 +10685 +8347 +18355 +5353 +13973 +19705 +13486 +12640 +18286 +7935 +15308 +19663 +3828 +9048 +2102 +4413 +15773 +18959 +5736 +11906 +10121 +7106 +12519 +14813 +8283 +17995 +18245 +17528 +9664 +17514 +12975 +19180 +10776 +5813 +8248 +10809 +5714 +18275 +17511 +3266 +6741 +18541 +15913 +11962 +17903 +16954 +11969 +10747 +10817 +4768 +12361 +4644 +1078 +10225 +15292 +7541 +16364 +8121 +10849 +10508 +12672 +13805 +12359 +3415 +105 +12544 +2669 +6109 +8445 +10024 +1011 +13058 +12643 +25 +10913 +18623 +4593 +3931 +12 +2221 +3544 +15357 +193 +8483 +7874 +4218 +19784 +17358 +18553 +9388 +13395 +10285 +7980 +15753 +13612 +14110 +8226 +12962 +9413 +2444 +3839 +8799 +8120 +14653 +1806 +6353 +16080 +4093 +7975 +16968 +2983 +11979 +11746 +11862 +5064 +8423 +698 +10196 +18712 +5556 +17463 +16295 +14169 +6756 +4706 +6466 +12484 +6914 +5041 +444 +9153 +10742 +9094 +6229 +14835 +1788 +8358 +17297 +8194 +15854 +19056 +5225 +12367 +3178 +7933 +18853 +13392 +12610 +5908 +11284 +15829 +358 +8681 +243 +9363 +17255 +15461 +15770 +8428 +9848 +9961 +2207 +18578 +18187 +4603 +3604 +1631 +11597 +18360 +15034 +17912 +4234 +4361 +4811 +2907 +2663 +4064 +5274 +10457 +7662 +13062 +2525 +3350 +10254 +8331 +18062 +10376 +5816 +14534 +3204 +4854 +15587 +13195 +3990 +14365 +4017 +18262 +5611 +11794 +13077 +9691 +12285 +13835 +10349 +19198 +11448 +15544 +1689 +13986 +16431 +1164 +366 +19223 +9911 +14965 +3609 +9947 +1315 +19685 +18734 +11761 +6602 +511 +18486 +17360 +19869 +18089 +14054 +19378 +19515 +664 +13338 +12624 +19588 +13516 +15006 +19774 +717 +19102 +18654 +17433 +4752 +3812 +10509 +14495 +679 +5734 +13129 +12281 +1133 +3697 +7499 +18278 +15640 +10425 +15827 +8545 +18831 +13749 +17888 +10938 +6204 +18059 +5646 +11803 +13074 +10833 +14143 +11005 +9293 +12834 +1786 +4866 +19249 +9836 +16392 +9181 +13855 +13176 +9478 +701 +9132 +1542 +8862 +12341 +17309 +18661 +16443 +4640 +14857 +8290 +17283 +5496 +14242 +8793 +4576 +4679 +11889 +1438 +4925 +10355 +3819 +6376 +2532 +13526 +14322 +10347 +18854 +5956 +19423 +15665 +8915 +4663 +10692 +19644 +15832 +18590 +8621 +13148 +1924 +17794 +9825 +15755 +10445 +19190 +17758 +14146 +6411 +2590 +8168 +15901 +3581 +6440 +15382 +14036 +13349 +6535 +6592 +13203 +3161 +4546 +8444 +17303 +18984 +15002 +8550 +19625 +19884 +233 +7041 +19499 +18047 +4468 +17987 +13641 +10589 +17550 +7576 +7093 +19113 +1199 +1380 +9182 +12319 +19033 +1001 +17730 +13731 +7802 +19430 +6872 +8684 +6579 +8562 +6561 +11864 +6199 +15051 +15499 +11065 +18566 +5996 +13174 +4025 +7480 +15136 +17700 +3085 +5949 +7681 +9905 +11608 +13104 +17189 +7514 +3618 +3353 +17233 +8916 +15953 +18436 +13280 +5084 +7360 +5594 +6404 +6187 +10143 +3949 +14028 +4990 +2245 +13736 +17844 +11748 +15719 +17244 +876 +3124 +15721 +14763 +5663 +11000 +18467 +6098 +17920 +2939 +6864 +7719 +2765 +5726 +16995 +13325 +11705 +18849 +8292 +3368 +13861 +16438 +6196 +17304 +18376 +4872 +1275 +2509 +2557 +2340 +7021 +2650 +1794 +12043 +14059 +9408 +18205 +18720 +13010 +17627 +11010 +17859 +17921 +10917 +12656 +5336 +8553 +6975 +4383 +4116 +14693 +11771 +6093 +26 +9224 +14712 +17335 +17173 +9586 +17776 +1680 +10825 +4244 +15878 +8628 +17165 +3066 +818 +7383 +15126 +18393 +10612 +15174 +5763 +12617 +14167 +5003 +3096 +13585 +1448 +9831 +3218 +16882 +15123 +18705 +2600 +15032 +7241 +11132 +3297 +13040 +18608 +9974 +14192 +13958 +7070 +8843 +7418 +4296 +4012 +5566 +16074 +5409 +5514 +14423 +10210 +9240 +10558 +8792 +4174 +13021 +2508 +8744 +3624 +9826 +2099 +2450 +4997 +8300 +9202 +7290 +8354 +9455 +11114 +7824 +18422 +16705 +14690 +5329 +6739 +15794 +1497 +2426 +5643 +15341 +4695 +17307 +18641 +16288 +6546 +3326 +1076 +6025 +19048 +5454 +11089 +10899 +16578 +1260 +17090 +2870 +11028 +12158 +13954 +17078 +18718 +16446 +9290 +4775 +1233 +19424 +15685 +18182 +11836 +5741 +18378 +11354 +1724 +11609 +10093 +5968 +19296 +16590 +3108 +10896 +12243 +11 +14765 +11872 +12395 +11295 +17536 +18464 +5233 +995 +13449 +11846 +427 +4382 +11744 +12932 +18627 +1129 +7773 +1205 +15155 +12680 +10125 +16326 +6385 +13849 +11225 +3097 +16889 +399 +10042 +15394 +7503 +3511 +3026 +16831 +2012 +7969 +15158 +13916 +15538 +19165 +15629 +3383 +1615 +4608 +8345 +2181 +15602 +2985 +1206 +13910 +17242 +9573 +10789 +13366 +9324 +627 +10717 +18922 +2137 +6038 +8617 +14878 +1819 +12227 +16619 +7412 +15689 +13830 +14674 +15857 +18942 +8806 +3933 +5087 +17243 +17602 +4797 +9471 +12786 +6785 +15817 +12382 +5942 +13423 +657 +766 +12638 +15369 +2293 +4261 +4313 +19519 +13182 +13050 +294 +11471 +9368 +3217 +8225 +3714 +416 +12791 +19712 +11496 +10593 +1969 +1261 +9453 +5450 +2264 +1520 +17027 +14102 +8043 +16588 +17379 +16002 +7426 +4960 +1687 +12676 +17614 +7422 +2558 +10843 +16071 +16109 +11505 +9696 +2708 +15539 +15414 +560 +12428 +3582 +9599 +12300 +404 +5525 +7065 +19368 +15657 +14440 +15111 +13909 +3300 +10929 +13225 +17587 +4320 +2199 +5742 +11038 +4081 +7977 +12058 +3130 +1240 +13057 +11639 +5235 +8789 +2850 +5839 +19562 +8872 +17666 +18377 +10257 +17356 +18091 +7705 +215 +9917 +7102 +18268 +16976 +9009 +16032 +7962 +7666 +15885 +7128 +14114 +17499 +12351 +7184 +1280 +9320 +12328 +19482 +11432 +8508 +6719 +16981 +1659 +14253 +13553 +17390 +8635 +10945 +13402 +1201 +15144 +18331 +1181 +5335 +10864 +16844 +11055 +4745 +6403 +13747 +1579 +6133 +8077 +7402 +17330 +10048 +102 +838 +6401 +12303 +14218 +9804 +17107 +13621 +10206 +881 +11995 +17268 +15072 +12536 +9458 +18251 +8868 +13994 +13206 +15980 +17688 +13754 +1299 +17566 +15345 +6375 +3924 +17069 +5004 +14362 +9065 +18043 +714 +18225 +15089 +3084 +287 +11080 +7256 +7701 +18466 +15354 +11668 +3553 +14395 +19915 +18786 +825 +19835 +13575 +1831 +247 +2016 +4286 +8007 +12230 +1643 +3260 +1430 +19238 +16397 +11291 +17482 +18813 +12673 +11067 +1375 +13775 +16079 +7496 +6538 +8212 +10677 +12710 +15102 +1845 +10450 +11695 +3706 +8988 +16641 +3005 +5552 +11908 +6518 +18416 +18560 +14484 +10812 +311 +6700 +2489 +4814 +6725 +8462 +8875 +8512 +6328 +7243 +15055 +18698 +12542 +10775 +5152 +5131 +5549 +16658 +17703 +10351 +15186 +9407 +13696 +14357 +4714 +18871 +6300 +5477 +222 +5256 +14735 +9200 +16765 +4856 +13549 +1656 +18619 +13966 +2214 +5952 +796 +8537 +3193 +5094 +16830 +11210 +11692 +11994 +8379 +17603 +2092 +13879 +18172 +15026 +4179 +16301 +19341 +9136 +11273 +5930 +7936 +5398 +14274 +18913 +13555 +14098 +1330 +2296 +12950 +16616 +11661 +2529 +6732 +14431 +12913 +13222 +3720 +11359 +18399 +9565 +18706 +17075 +12089 +17130 +2672 +5208 +15159 +9660 +3923 +2693 +16745 +2934 +9287 +13990 +4122 +17963 +6070 +2628 +19739 +6648 +8719 +17515 +11774 +15489 +14652 +5338 +4892 +3433 +4484 +11632 +9010 +3033 +8230 +3200 +3977 +17847 +8202 +18675 +1119 +10056 +1413 +7573 +14341 +1036 +17108 +12098 +4137 +3651 +13379 +7904 +10641 +14976 +2180 +10944 +19356 +473 +16989 +8832 +15224 +6890 +2891 +2126 +4276 +11488 +12117 +6388 +4027 +8068 +409 +17687 +18778 +4822 +414 +18290 +3038 +6865 +10262 +14837 +10141 +9792 +13545 +18885 +4761 +4475 +3529 +19217 +19693 +3348 +7212 +18332 +7372 +12269 +3032 +11697 +16051 +13558 +2718 +19082 +6046 +11137 +6485 +9052 +14647 +13333 +5828 +4397 +7386 +8605 +5651 +6024 +5189 +16345 +15434 +14725 +4514 +11023 +13382 +7578 +13239 +4532 +15295 +11892 +9545 +2152 +14703 +18904 +8531 +15223 +18084 +4524 +74 +367 +3302 +15187 +17948 +5692 +6128 +6172 +862 +1800 +4684 +9414 +11033 +13573 +6000 +9615 +17476 +9059 +4805 +17054 +8582 +11549 +5650 +12626 +14308 +2238 +11714 +566 +5316 +2751 +4733 +970 +18769 +12843 +4658 +6209 +8830 +18171 +19497 +14780 +3730 +2661 +12284 +7012 +12277 +10008 +11933 +3142 +18428 +3667 +161 +12152 +12630 +18370 +7939 +2046 +3771 +16803 +13993 +2129 +14608 +18839 +12060 +16404 +11870 +18923 +10698 +6659 +2352 +1561 +4226 +14741 +17692 +9649 +5073 +15142 +19353 +6009 +3240 +5344 +10170 +4550 +17907 +11679 +7651 +6796 +397 +7148 +12621 +5558 +3054 +14049 +2090 +13856 +12317 +10660 +2514 +14338 +10482 +19202 +11648 +16403 +1335 +19574 +16665 +11989 +4482 +16313 +4481 +17290 +3742 +4407 +1528 +12901 +7516 +15834 +10231 +4945 +11337 +12609 +5516 +17039 +18026 +11509 +15831 +6085 +976 +18368 +2249 +17712 +16657 +2085 +1054 +1880 +6681 +8094 +9636 +18833 +14291 +7659 +11754 +19714 +17347 +1565 +18074 +7791 +6470 +2289 +10027 +1934 +12826 +19295 +17179 +6112 +15008 +17860 +9711 +12338 +18888 +9216 +17573 +15741 +6557 +11821 +3785 +13764 +14853 +5129 +15446 +1243 +2836 +11920 +4115 +19743 +1410 +16817 +18379 +3104 +5661 +13223 +4483 +2670 +945 +17124 +4863 +13476 +18169 +15448 +18006 +19349 +8378 +1572 +12920 +7204 +4230 +19243 +9426 +12260 +16377 +10194 +2825 +4908 +11368 +3711 +19583 +17367 +292 +12903 +16330 +5391 +13254 +494 +16445 +13690 +7236 +15348 +14251 +9734 +13249 +16374 +11516 +7995 +5557 +5923 +11866 +7832 +5799 +19500 +8329 +18652 +19034 +5186 +14753 +1061 +3947 +5497 +4861 +9169 +15018 +12213 +2179 +13884 +5766 +4358 +14866 +3880 +19470 +14598 +11652 +10155 +19732 +13138 +4287 +131 +16430 +7010 +4214 +12811 +1373 +9830 +13243 +3291 +12009 +14404 +3379 +12855 +1414 +13853 +14429 +4053 +3056 +4022 +9318 +7637 +3941 +5417 +16719 +8978 +16432 +19505 +12738 +1730 +16789 +18145 +18371 +3497 +8119 +7470 +17800 +13870 +18571 +6554 +11431 +14445 +7197 +1933 +15623 +12777 +7361 +13844 +143 +10883 +14593 +11806 +2645 +17512 +6887 +18030 +3128 +4333 +8911 +10198 +12129 +5486 +8823 +17547 +14551 +11753 +10950 +16379 +8214 +2067 +18622 +17927 +14904 +4844 +14790 +5246 +12162 +10631 +649 +15091 +14794 +11946 +6781 +17949 +15902 +6055 +8503 +9719 +7506 +15682 +4291 +15994 +13645 +9256 +4156 +12447 +7339 +3122 +3601 +19670 +15202 +14577 +17212 +6424 +6674 +4651 +2075 +8017 +8278 +12156 +8651 +5077 +1480 +3701 +4011 +9612 +17701 +12062 +19899 +15976 +12877 +14421 +18792 +6460 +12295 +13661 +3963 +3847 +12668 +5080 +16134 +2026 +12629 +10804 +10771 +12274 +214 +4299 +9503 +19905 +6019 +2035 +6059 +17521 +5218 +16809 +536 +6746 +12068 +9279 +19432 +15122 +10060 +10991 +6585 +1998 +10142 +3087 +11964 +1525 +1860 +11818 +2219 +14103 +13693 +5011 +7139 +13527 +5879 +7955 +9316 +16697 +8869 +11251 +1534 +4284 +733 +17527 +5569 +14351 +17418 +15542 +14860 +9767 +13284 +15301 +15678 +15219 +17311 +11024 +5699 +4445 +12438 +13540 +746 +6888 +19798 +6721 +1389 +145 +4078 +8049 +15621 +6921 +12862 +14073 +18173 +10683 +5789 +18085 +2374 +16355 +14745 +12662 +4894 +8104 +12685 +6399 +13724 +10841 +18069 +9887 +2652 +11241 +18298 +8535 +8474 +16926 +9249 +7268 +6697 +19167 +1891 +11305 +8575 +18527 +6213 +8178 +13619 +19999 +18898 +13321 +10640 +8731 +7009 +7686 +2565 +4069 +12508 +15261 +2480 +18716 +17238 +15868 +8197 +19619 +14934 +18585 +10536 +767 +13067 +8857 +18953 +16893 +13144 +19008 +4964 +9658 +4364 +9335 +8459 +379 +18910 +3409 +6979 +1409 +4906 +15490 +630 +2038 +2139 +5842 +6783 +696 +18035 +4543 +14226 +19690 +5147 +9021 +6036 +1128 +4325 +13201 +18119 +10323 +9701 +9494 +10550 +18311 +15527 +19917 +1122 +3407 +19589 +4884 +11907 +196 +19568 +6717 +13372 +13179 +16909 +14987 +6436 +14334 +5811 +15522 +1797 +3359 +15798 +8064 +7523 +11405 +15664 +8189 +14549 +19802 +2658 +3425 +14066 +15800 +11281 +16488 +9329 +8763 +10973 +3798 +5228 +3687 +13819 +9967 +3652 +8239 +8705 +8318 +10694 +7897 +9937 +11380 +17016 +10220 +12399 +17621 +1650 +17071 +14603 +15735 +7510 +3269 +17403 +4318 +3343 +2797 +3306 +3109 +5897 +3526 +9286 +14601 +10375 +16691 +10859 +16013 +14381 +1922 +8004 +7460 +19022 +10605 +14881 +8109 +16389 +9692 +435 +5 +1713 +7550 +12168 +4808 +9708 +9148 +4876 +16569 +6508 +13657 +17582 +1709 +1232 +16140 +4037 +17249 +14610 +1293 +8356 +7380 +8971 +14378 +19185 +16906 +15180 +14222 +3003 +8038 +17821 +11942 +18488 +10903 +11667 +608 +2157 +12806 +8649 +3983 +16528 +14 +15311 +17327 +13842 +19256 +16648 +184 +9485 +15858 +1309 +4362 +16655 +17745 +13184 +9441 +4408 +16967 +19195 +16827 +16671 +9188 +3824 +18471 +6317 +14144 +13056 +10402 +1108 +18707 +4121 +16297 +11827 +18002 +19301 +16290 +10822 +7114 +17389 +534 +2364 +1159 +17258 +18341 +6967 +13564 +2743 +6768 +8031 +18141 +363 +18456 +14654 +7884 +19790 +8115 +12111 +8521 +12506 +7756 +7607 +5973 +8925 +18952 +11686 +6895 +5100 +9731 +3107 +7847 +1580 +4143 +2344 +7721 +7342 +13237 +6268 +12144 +4032 +10943 +4063 +565 +15758 +18159 +1539 +14732 +8563 +18624 +7076 +9595 +13354 +4046 +7679 +5455 +14993 +13154 +4082 +2148 +10549 +12991 +5394 +4182 +12226 +16029 +19740 +16292 +4952 +19380 +10330 +10990 +17685 +6678 +6527 +18455 +17874 +9650 +18494 +3807 +2346 +6256 +11483 +1874 +14111 +10073 +10328 +692 +10003 +10563 +9710 +8137 +3685 +16689 +129 +6753 +5559 +12231 +1290 +4105 +8819 +5636 +14720 +5296 +11586 +16631 +7615 +11047 +14797 +7355 +1883 +14151 +8546 +15245 +11203 +1408 +11596 +1398 +4197 +14191 +7156 +16091 +19409 +1633 +5277 +4310 +6226 +454 +9288 +5453 +9412 +3163 +5238 +10146 +6151 +2424 +4145 +18612 +16892 +19907 +5693 +15343 +12492 +13020 +965 +4898 +17448 +4652 +10150 +17739 +16189 +4860 +4473 +8136 +8583 +7726 +1771 +2539 +8935 +12164 +12192 +11527 +5119 +14890 +9766 +2570 +16100 +9570 +14602 +16325 +7391 +6299 +14230 +8447 +5740 +6443 +14046 +17740 +10235 +19488 +13597 +2875 +17644 +16773 +1058 +12614 +13906 +16543 +16394 +14939 +14905 +11468 +18827 +18564 +19462 +13002 +14430 +13677 +9396 +5223 +16987 +11600 +8430 +6621 +13135 +12534 +4158 +10596 +14768 +3334 +16593 +7267 +82 +1042 +13700 +13928 +3593 +2728 +17783 +13616 +18860 +16477 +1884 +3341 +4455 +8523 +5360 +6744 +9787 +712 +12234 +64 +9539 +6601 +14071 +18366 +5169 +15012 +16284 +4748 +2977 +5519 +8456 +7158 +8475 +9258 +16579 +8251 +3106 +10428 +19736 +1630 +16367 +4317 +15059 +16195 +7278 +5500 +8624 +6245 +18284 +12479 +4221 +17256 +17119 +135 +9422 +8909 +7927 +10264 +13017 +7051 +12580 +4089 +192 +11988 +6610 +19422 +8392 +17224 +5795 +5322 +1995 +6348 +9236 +4495 +6127 +19207 +16255 +4836 +9538 +19629 +14271 +11400 +3575 +18824 +4141 +15209 +13699 +2686 +14671 +6450 +13634 +18974 +19253 +14865 +16388 +18247 +1431 +12762 +7066 +5608 +5924 +6989 +14656 +9274 +6333 +15028 +6261 +1608 +11467 +19389 +13533 +1491 +3458 +1015 +2794 +8610 +18369 +7108 +7727 +10071 +19320 +8491 +12090 +8934 +3015 +9067 +16834 +4963 +14605 +18596 +2405 +1991 +6503 +15378 +8231 +17919 +4285 +2496 +555 +793 +2366 +13341 +18687 +1202 +6599 +17973 +11949 +9640 +5875 +12414 +14414 +6094 +10920 +13905 +18533 +10406 +13899 +8976 +1188 +7873 +19188 +12857 +16770 +10304 +18077 +9698 +17593 +12390 +11536 +9862 +5744 +5033 +13998 +5743 +1031 +10481 +9928 +5362 +5057 +5149 +18682 +5295 +2131 +5474 +8808 +3726 +14455 +4422 +12459 +8650 +17260 +14754 +15993 +5910 +18194 +19914 +4904 +11235 +6712 +2430 +9566 +7643 +19651 +10145 +19816 +18051 +15056 +6195 +2502 +12838 +259 +8380 +13378 +5311 +5826 +19153 +13762 +14531 +12340 +19532 +4780 +15970 +5958 +17384 +15415 +11795 +9404 +7356 +11945 +8321 +10830 +321 +18044 +5786 +6319 +12251 +10016 +2739 +7976 +15319 +4319 +4911 +5599 +12753 +11303 +1210 +10440 +11546 +6635 +18617 +19729 +662 +18724 +16559 +17829 +8114 +19373 +14057 +16199 +5306 +2419 +3513 +17503 +3405 +1569 +15166 +3577 +15124 +9460 +3982 +12280 +18257 +5138 +15084 +5883 +3655 +18036 +18505 +11417 +7229 +11943 +19333 +7107 +19524 +4591 +754 +17184 +9066 +5834 +11322 +8985 +3984 +13421 +3023 +13334 +18132 +2854 +7330 +5410 +18118 +4630 +6441 +12951 +7407 +170 +12047 +5117 +683 +3403 +5236 +48 +14544 +18723 +2059 +816 +14524 +6826 +17732 +7325 +17945 +14759 +16490 +12132 +8464 +7878 +12376 +13459 +304 +11191 +13578 +3797 +16282 +3876 +14933 +9528 +3901 +16331 +429 +7880 +2484 +3398 +19582 +1596 +933 +9747 +18174 +2976 +12715 +1793 +8877 +2291 +2237 +6528 +16638 +6294 +279 +16974 +11660 +14995 +6694 +8041 +10029 +7527 +4754 +4013 +671 +7549 +18405 +12204 +9904 +11927 +11064 +7059 +14336 +4228 +15510 +1463 +1763 +17946 +1144 +14279 +15274 +9282 +16781 +17761 +14361 +4040 +9075 +19980 +4399 +13015 +8746 +17579 +17764 +18041 +7678 +3115 +14892 +13945 +4227 +1014 +5415 +570 +18354 +18808 +19142 +6619 +19507 +15353 +1381 +10597 +14597 +11939 +11383 +4369 +19836 +18420 +11034 +15451 +2912 +13181 +17693 +1844 +14101 +6400 +4602 +813 +17818 +14729 +13534 +10620 +18667 +3751 +15942 +9006 +10752 +11965 +13946 +2648 +11486 +19726 +7409 +11815 +15088 +1116 +5694 +1914 +433 +14816 +9631 +17106 +7899 +14328 +6912 +485 +16628 +11183 +17172 +7634 +10806 +5383 +16801 +14746 +19564 +19742 +13883 +13397 +15364 +1255 +2775 +12225 +7235 +19495 +3944 +17472 +1581 +19200 +7814 +3585 +19346 +14017 +899 +18850 +4157 +16396 +16035 +8732 +13932 +17177 +13345 +19379 +1145 +897 +17560 +4224 +16014 +16988 +4311 +13296 +1552 +10120 +13326 +5962 +16790 +19631 +10321 +10996 +4099 +17222 +7567 +18442 +19656 +6238 +19874 +16230 +12050 +2236 +11548 +7056 +14571 +1382 +1642 +14526 +14518 +16550 +6581 +19885 +223 +7449 +1605 +16119 +10624 +15328 +2097 +10058 +6965 +5217 +1196 +11506 +4668 +9397 +4270 +18060 +11229 +7898 +7554 +13048 +13155 +15733 +4900 +1715 +12112 +3515 +16874 +9746 +42 +13347 +11552 +1110 +3879 +19871 +974 +7765 +6836 +3355 +124 +13405 +1469 +13989 +11169 +14533 +1105 +3168 +15740 +18925 +9135 +736 +13177 +1101 +13116 +19539 +19803 +11259 +10571 +93 +4170 +2136 +2149 +8315 +5835 +5146 +16683 +14300 +8141 +14570 +16242 +10722 +6364 +11082 +13458 +8339 +7965 +6334 +16884 +12771 +14021 +550 +8998 +51 +17976 +19806 +703 +1339 +4380 +8285 +9915 +9806 +16158 +3052 +18125 +1999 +18684 +13119 +2395 +8639 +19154 +2367 +19891 +5733 +14450 +8069 +17660 +16498 +997 +1941 +7448 +8520 +14805 +6120 +11676 +14629 +186 +17567 +5106 +355 +8831 +8257 +18066 +19011 +17346 +17940 +17746 +3905 +11148 +14121 +16966 +9385 +13780 +6134 +13248 +17871 +19839 +8060 +2276 +19749 +2901 +15838 +16115 +7095 +8085 +16777 +1674 +10712 +15745 +3953 +3837 +8037 +10572 +9635 +14477 +11699 +827 +5470 +5852 +9543 +1751 +5889 +18669 +16258 +9054 +17331 +13029 +12408 +4429 +10307 +15826 +14301 +973 +16123 +276 +16012 +9945 +18403 +15923 +17262 +15662 +9810 +9923 +7320 +8457 +16911 +10992 +14162 +12969 +10473 +16845 +16935 +3251 +11115 +8087 +12731 +9823 +5242 +7432 +10216 +18202 +10939 +17401 +15813 +3446 +3081 +18924 +15029 +16668 +317 +3012 +19552 +11206 +6558 +6081 +3628 +9662 +6419 +15498 +13943 +15513 +7818 +990 +6923 +68 +15508 +15161 +5127 +4534 +9165 +3951 +8100 +14187 +16434 +18842 +10691 +1620 +14783 +7801 +3241 +2583 +10907 +14552 +19695 +3846 +13358 +2516 +6664 +13523 +1545 +11097 +17269 +19369 +14156 +17245 +17640 +14426 +780 +17131 +11392 +4758 +7819 +19694 +6701 +6 +13947 +17021 +17924 +7401 +4138 +322 +13588 +10490 +8715 +8267 +6898 +10476 +5051 +17392 +3042 +14317 +17980 +6122 +13792 +12560 +11510 +15968 +13481 +17974 +2988 +14875 +4936 +10290 +6408 +3543 +8371 +13400 +19824 +6448 +92 +5547 +6228 +15940 +19420 +2314 +14093 +19285 +16682 +17955 +18802 +7961 +15630 +16023 +11819 +13723 +10369 +3833 +9724 +14906 +18783 +8086 +12179 +6687 +19870 +18518 +4144 +16795 +4781 +14676 +9051 +16876 +6409 +5315 +12644 +1062 +2581 +14210 +14092 +18300 +7029 +15641 +9977 +12109 +13322 +1312 +7861 +8218 +17468 +156 +12623 +14235 +16161 +18642 +16952 +15766 +5871 +7614 +18929 +6142 +12679 +18408 +15070 +1377 +12570 +13385 +16243 +17250 +18081 +19255 +506 +3915 +571 +12497 +4080 +19023 +8920 +6752 +7676 +4499 +4480 +16328 +16656 +14090 +8466 +9488 +2876 +11340 +19962 +7599 +136 +11041 +1976 +13485 +15259 +6786 +16277 +17096 +6086 +1155 +1056 +7694 +19490 +14437 +7592 +19787 +5475 +17600 +2226 +18997 +9883 +12463 +12711 +6354 +2538 +13032 +13256 +5251 +9382 +15900 +342 +60 +14505 +10564 +16440 +18611 +12910 +4570 +5290 +6246 +12646 +12124 +11903 +4114 +5877 +14619 +16366 +17310 +8269 +8063 +12941 +5439 +4672 +13660 +19265 +6164 +691 +5819 +19567 +3586 +12884 +463 +3722 +9383 +15725 +13096 +18398 +16383 +2272 +12977 +14807 +9041 +1445 +4237 +6946 +15317 +1607 +11531 +11336 +16343 +4271 +19812 +6220 +2839 +8725 +13567 +3746 +7737 +8132 +5393 +1279 +19012 +9170 +12350 +7839 +19813 +840 +3313 +7600 +12378 +19107 +5762 +4650 +17686 +601 +13133 +8396 +3794 +19 +13838 +3387 +5441 +12389 +15696 +10875 +12803 +16761 +5972 +5866 +15504 +17399 +8488 +2958 +18573 +8886 +16413 +5205 +13433 +10655 +661 +6616 +15515 +7253 +8342 +2612 +3134 +4165 +4972 +782 +1829 +994 +12931 +12936 +4155 +13115 +4503 +15575 +12267 +17414 +16263 +6652 +15759 +8463 +2156 +4001 +17493 +17236 +10519 +15734 +9902 +2899 +12783 +11925 +19649 +18825 +15683 +18897 +18155 +278 +13790 +6180 +14615 +5616 +9942 +12801 +15687 +5249 +6727 +11421 +16176 +15891 +16112 +3219 +19367 +10367 +12593 +2889 +6144 +650 +12616 +7037 +8346 +808 +18834 +15385 +2616 +617 +14786 +12559 +19508 +17657 +9012 +19716 +4107 +8946 +956 +12154 +4215 +11869 +16151 +17287 +18666 +5318 +6745 +10410 +1067 +8018 +5305 +1983 +18588 +12684 +8572 +529 +13503 +5510 +6185 +14035 +10441 +1183 +7232 +9933 +12188 +18404 +3853 +11560 +15524 +789 +10959 +5000 +6490 +8541 +16202 +544 +19494 +8642 +4562 +4776 +19919 +13538 +18005 +9880 +8858 +13826 +16786 +4957 +16752 +4800 +15603 +9596 +16896 +2578 +12051 +7294 +17473 +3669 +11445 +18692 +6846 +10007 +4470 +5649 +16365 +5376 +13628 +13590 +5188 +2250 +2390 +14215 +18135 +420 +1652 +13217 +7493 +12689 +7716 +13398 +4297 +18088 +12986 +7571 +13886 +2045 +18737 +18243 +18971 +3610 +14397 +3579 +15336 +6321 +6391 +1719 +17319 +17572 +15230 +6030 +17246 +9619 +12294 +2268 +15325 +9604 +14781 +17879 +3826 +4181 +15004 +12981 +11931 +3501 +12309 +19467 +16188 +8 +5761 +5047 +7931 +9004 +17186 +14911 +2842 +1834 +19606 +12927 +12540 +17812 +13687 +17206 +9098 +16417 +11704 +486 +2431 +17720 +11230 +4778 +19738 +8234 +1102 +15532 +906 +10229 +4889 +16302 +10964 +9673 +4084 +9912 +3422 +7104 +14634 +10845 +10107 +11378 +14685 +2387 +18342 +15699 +3608 +13286 +12217 +5020 +16120 +8543 +12979 +15796 +6285 +16456 +4969 +18845 +751 +6159 +16228 +2015 +3849 +9102 +849 +13417 +1778 +2108 +810 +6833 +17100 +4136 +4526 +348 +17187 +272 +5831 +16304 +12874 +7566 +4659 +3616 +9359 +18645 +3395 +8105 +1424 +14024 +18314 +18123 +2361 +17857 +2684 +2114 +8646 +10010 +17429 +12024 +10773 +6044 +9399 +16045 +542 +15225 +7062 +17619 +4266 +9973 +17451 +11670 +749 +9490 +5913 +5705 +19084 +13556 +7908 +8753 +1939 +5448 +15643 +11219 +6994 +5668 +7353 +19668 +18092 +2999 +15511 +18207 +2458 +9269 +18782 +14041 +19358 +18175 +7113 +5123 +11606 +13263 +17892 +16218 +17449 +302 +8544 +15266 +19465 +15546 +10679 +13494 +6645 +18063 +12033 +8167 +4509 +13501 +258 +18154 +12290 +955 +13412 +12081 +7255 +3542 +11523 +5713 +16957 +10784 +19886 +6200 +12116 +10209 +10858 +18213 +4051 +5413 +3900 +5108 +16709 +17534 +19460 +8025 +8304 +7176 +9374 +3312 +4346 +8566 +19106 +6582 +14715 +12146 +18011 +1930 +353 +4631 +212 +7994 +9144 +18080 +12526 +18229 +5619 +6973 +19112 +9953 +5365 +7482 +3955 +19937 +7042 +13816 +17966 +2216 +9590 +17203 +8882 +4918 +5865 +17565 +10643 +6811 +12356 +3950 +3632 +5804 +2244 +15663 +19481 +19534 +14651 +15785 +152 +13732 +2563 +13773 +11820 +12989 +7313 +16704 +8337 +19352 +7817 +2633 +15432 +8955 +18497 +15417 +8848 +4148 +3764 +10395 +14673 +2832 +6877 +15756 +19707 +4682 +8989 +9450 +2535 +9723 +6006 +12912 +2255 +521 +7730 +277 +15079 +8893 +11751 +318 +15397 +6416 +4171 +12817 +12345 +11092 +19364 +18796 +19477 +5517 +5241 +14964 +10554 +16073 +5680 +9393 +12410 +305 +4274 +4973 +7369 +15226 +5568 +12591 +2721 +9655 +11535 +9032 +8160 +10585 +16016 +7561 +8812 +9828 +5266 +1351 +5358 +7389 +3806 +18586 +12487 +15436 +4986 +9498 +12180 +4337 +15483 +8271 +11957 +16279 +9859 +15845 +1502 +11066 +6412 +2620 +3718 +14954 +19976 +10790 +4471 +4189 +18102 +18519 +14333 +12339 +17361 +8204 +4937 +1295 +19094 +868 +4859 +19365 +3413 +1775 +13156 +5936 +5390 +11015 +2632 +11963 +7828 +6039 +3276 +5656 +17665 +7501 +1080 +9674 +11243 +7922 +11042 +6307 +13892 +13940 +9482 +8866 +15118 +6576 +1784 +17951 +1901 +8366 +17129 +10200 +16885 +19240 +16170 +3948 +3835 +7631 +12396 +19611 +17295 +9348 +8686 +12530 +3715 +3212 +9841 +8213 +1604 +11849 +1684 +465 +10127 +6136 +10256 +1758 +13323 +1538 +17436 +2032 +12036 +8338 +10050 +17148 +14112 +15592 +5090 +13384 +15492 +15339 +13173 +6208 +4736 +18764 +18690 +18124 +1396 +18789 +9741 +18713 +10086 +16093 +4799 +19020 +1485 +365 +17407 +15632 +3063 +5342 +13070 +1329 +8878 +11152 +13787 +15979 +4891 +16398 +7218 +11289 +18249 +5469 +11418 +10870 +1887 +16429 +8675 +7986 +11159 +5387 +58 +9168 +16846 +17467 +9452 +17447 +16503 +651 +5458 +6370 +10169 +10063 +18820 +406 +17339 +17417 +1384 +19709 +12480 +9303 +2448 +5043 +6791 +3077 +6666 +19340 +17611 +10865 +9900 +11742 +12695 +17002 +14767 +11634 +17841 +19678 +9097 +11650 +1808 +110 +1770 +10863 +17491 +14461 +3759 +5698 +12149 +19093 +17735 +5231 +2271 +14514 +12100 +13467 +2066 +2445 +15481 +5126 +3149 +16664 +6392 +10399 +65 +7855 +7970 +18525 +6126 +15844 +5768 +18805 +9621 +15101 +5300 +19530 +5312 +4151 +13860 +19004 +1266 +10777 +5150 +4816 +5172 +252 +702 +5823 +5863 +11111 +11508 +13339 +3729 +10030 +9843 +2624 +17380 +8679 +3709 +8051 +9589 +3365 +3280 +18010 +15057 +230 +12690 +8969 +11484 +19218 +13348 +17118 +2100 +14262 +10255 +594 +19852 +7830 +19461 +5345 +5502 +6363 +2256 +13852 +17012 +2494 +19958 +4995 +15409 +6789 +3974 +10122 +1511 +7786 +1248 +8127 +13084 +2500 +18524 +19013 +5258 +15961 +3004 +5337 +523 +19968 +6275 +8662 +19779 +10343 +1977 +15801 +12321 +16162 +7341 +9281 +14796 +9310 +19512 +19405 +19782 +14145 +13741 +19751 +150 +11990 +11568 +9552 +1184 +11165 +2873 +17804 +18743 +14394 +16041 +15676 +8228 +15025 +8795 +720 +5934 +349 +16651 +11366 +19021 +424 +14289 +2211 +8771 +5009 +18528 +17697 +19558 +3653 +11674 +14124 +6360 +18317 +13045 +16862 +17105 +14501 +10910 +18357 +13959 +17312 +11254 +6699 +1163 +14463 +17133 +1379 +3424 +19235 +16506 +13474 +2966 +750 +6251 +17774 +6665 +11172 +16449 +18591 +11218 +15077 +11681 +7650 +1566 +16690 +971 +5472 +19354 +623 +5621 +14700 +9018 +15048 +10975 +12805 +2052 +19103 +16048 +12467 +6146 +11128 +13798 +16299 +5624 +11716 +15569 +12681 +19003 +14089 +5005 +17643 +18054 +8507 +624 +9764 +430 +5139 +12955 +17633 +18795 +1088 +19129 +843 +19819 +14469 +15666 +4582 +9920 +13681 +10066 +8065 +9648 +2202 +96 +7484 +1267 +690 +16179 +3182 +5125 +10811 +5724 +15850 +2222 +9046 +6423 +13733 +15684 +15392 +17495 +12863 +498 +10164 +18966 +12418 +6222 +9976 +288 +16999 +15426 +13872 +14451 +9547 +10515 +7344 +854 +7902 +2768 +15997 +19294 +17308 +12595 +18887 +2689 +6909 +12091 +12844 +3926 +6542 +15474 +18227 +201 +5498 +17574 +4109 +9572 +4954 +6101 +7505 +16538 +16793 +17192 +17517 +351 +5133 +2050 +1282 +18186 +11233 +14645 +19337 +6158 +3351 +914 +5701 +3136 +5414 +1420 +11999 +11489 +7586 +442 +7805 +3809 +3138 +8291 +13592 +16618 +16338 +2127 +3972 +5562 +9028 +14912 +5653 +4166 +3743 +7872 +599 +6954 +10668 +2845 +19100 +16617 +154 +11374 +6779 +14547 +13415 +17097 +18994 +8608 +14527 +2486 +1154 +17689 +7869 +15346 +2994 +13851 +7350 +5431 +19834 +13357 +5989 +17009 +10533 +2351 +14369 +2285 +15677 +15380 +1910 +13132 +5639 +4735 +3009 +12004 +14330 +12835 +7845 +19647 +4479 +7473 +9394 +11296 +5279 +7863 +10458 +3954 +8373 +5988 +1220 +461 +2378 +14855 +5317 +10956 +1916 +4531 +4698 +15306 +11094 +12270 +13226 +8061 +14314 +9906 +8102 +11665 +3427 +962 +4411 +9899 +4033 +2513 +18110 +12481 +6737 +3661 +13591 +1504 +5545 +17726 +11208 +2362 +17204 +12377 +13014 +15207 +4708 +2123 +18387 +10018 +10180 +3360 +13529 +972 +12769 +6091 +11867 +2515 +17622 +7430 +18493 +19051 +18031 +221 +9493 +18830 +106 +12860 +6790 +1446 +1412 +3044 +4097 +9986 +3684 +9728 +656 +8351 +10291 +19880 +9679 +3629 +15564 +7370 +13046 +5887 +11953 +12133 +5966 +3892 +19597 +7750 +707 +5503 +1714 +9459 +12006 +1362 +12357 +14220 +5717 +18583 +1321 +15403 +19546 +3620 +890 +17508 +4586 +9158 +15310 +923 +17278 +6502 +9406 +1790 +1540 +16916 +14091 +13304 +4494 +10326 +2230 +56 +13219 +17320 +14202 +15503 +3861 +78 +10493 +4999 +1081 +17061 +11221 +10599 +12757 +8972 +1653 +15651 +9007 +3796 +5485 +14396 +13088 +4283 +5605 +13224 +12841 +4878 +9395 +10511 +11666 +4720 +5286 +9628 +18394 +3878 +16354 +4939 +8961 +14625 +19956 +1130 +227 +3913 +5466 +3840 +8302 +5604 +10791 +985 +7015 +210 +8742 +3455 +14814 +15884 +6188 +10504 +18972 +5749 +9758 +7990 +1103 +17428 +17696 +7485 +18153 +16044 +19587 +7929 +14339 +14636 +8643 +19199 +16971 +1486 +11765 +10794 +11709 +7038 +9211 +19761 +10590 +18417 +15283 +3850 +11144 +11415 +17838 +8117 +19322 +9644 +18451 +12386 +7331 +17077 +1241 +13242 +11125 +18440 +6857 +14276 +948 +13000 +13679 +18108 +14331 +14504 +9428 +15808 +15276 +1889 +15889 +7092 +4491 +9983 +5339 +14909 +2277 +18390 +8313 +19687 +2677 +15712 +4442 +8932 +17952 +9513 +9342 +16675 +14298 +11027 +2809 +12147 +16592 +1466 +9322 +17985 +1361 +15154 +6515 +15035 +3816 +7558 +11435 +19043 +6607 +13969 +4050 +19652 +17195 +16509 +18631 +13091 +121 +4472 +6568 +63 +12768 +10195 +16562 +13875 +19791 +1584 +7606 +4387 +15320 +11616 +711 +3083 +9262 +10710 +431 +15922 +17958 +4246 +513 +4971 +15273 +4172 +179 +3030 +3110 +17836 +3411 +7670 +12478 +2343 +11805 +5184 +18447 +4592 +12949 +16164 +8917 +14532 +10124 +14711 +18508 +5684 +2267 +15883 +5745 +19792 +5436 +3051 +8936 +8933 +11459 +14963 +7533 +14460 +16624 +19992 +10765 +10332 +14389 +13601 +10117 +19429 +7209 +5347 +2379 +4765 +12342 +17445 +13760 +6061 +13939 +3600 +4168 +17313 +11921 +7373 +2793 +4088 +10740 +9908 +1873 +13799 +11871 +6386 +17673 +18756 +6457 +9522 +14324 +7836 +19278 +19573 +14453 +710 +12582 +6241 +16363 +8485 +16552 +14762 +15601 +5534 +14245 +13043 +16439 +17385 +10985 +13933 +12906 +3602 +727 +18115 +3648 +17155 +10543 +8471 +13825 +10986 +5137 +9331 +15772 +18383 +11781 +10937 +10474 +3173 +13848 +10555 +15690 +7083 +3299 +12421 +5542 +9260 +14095 +9350 +14971 +6232 +7345 +77 +17822 +374 +912 +14680 +12700 +10161 +16652 +18815 +16724 +4907 +5555 +12470 +7205 +578 +7780 +851 +1865 +16522 +9008 +7293 +9463 +3192 +18536 +5030 +4959 +18579 +4587 +6512 +1024 +10980 +10898 +13636 +3095 +18779 +1733 +12699 +16512 +16480 +1179 +10921 +14594 +14388 +18748 +8898 +7486 +55 +17440 +9243 +1668 +8540 +13289 +9436 +17648 +346 +12871 +16749 +164 +12634 +19758 +8937 +15947 +1861 +17849 +4989 +12096 +16698 +11948 +8399 +12457 +15480 +12110 +11619 +16899 +11292 +9074 +5373 +14465 +15305 +10982 +6406 +112 +1284 +9356 +13890 +8959 +15879 +580 +7714 +5506 +3190 +17881 +14872 +4306 +18338 +9994 +17684 +17898 +87 +472 +6161 +4723 +3447 +18148 +3158 +18542 +4948 +3738 +5297 +19281 +14788 +15127 +13776 +13611 +10153 +7853 +12450 +10108 +14227 +19753 +6458 +1003 +19973 +15140 +6123 +16735 +6928 +4327 +10420 +16963 +940 +19622 +17196 +1925 +10566 +9358 +12819 +2030 +9681 +10077 +4334 +6690 +14318 +16043 +426 +1151 +8349 +4942 +5598 +2853 +19639 +11215 +4920 +13434 +9791 +2586 +5757 +5697 +14377 +16353 +18217 +8190 +10013 +18738 +19502 +18120 +9467 +9864 +16532 +11069 +8612 +1937 +1372 +15299 +16473 +5612 +12577 +15073 +716 +13517 +16768 +18633 +14902 +15125 +1093 +2678 +7539 +5928 +6696 +8923 +10954 +2918 +12820 +2851 +16694 +7692 +16254 +19650 +2386 +4220 +4701 +4004 +17718 +2989 +6924 +477 +5937 +9535 +4961 +16542 +12774 +1691 +10135 +14188 +17597 +15935 +14882 +4357 +13662 +18206 +8885 +5504 +7217 +5111 +5964 +11358 +3451 +8604 +8519 +15887 +12545 +982 +16497 +11323 +11385 +18188 +19645 +10984 +15886 +2551 +6679 +12606 +10824 +3956 +11180 +7574 +4028 +16212 +3914 +7677 +14076 +13885 +11514 +1767 +10012 +12423 +9778 +2821 +2811 +7956 +769 +14842 +19029 +13439 +18214 +2223 +3792 +10346 +9860 +517 +15205 +19674 +15361 +16625 +14219 +16820 +19101 +4351 +640 +18765 +11121 +4350 +16482 +6707 +6810 +14542 +2791 +8006 +12823 +689 +2929 +19232 +8752 +1342 +7597 +19672 +16838 +830 +14492 +16941 +14633 +3724 +989 +4184 +1453 +8029 +3327 +3677 +16206 +2457 +17398 +8335 +10118 +266 +5533 +4680 +11379 +17478 +9527 +19617 +1678 +10329 +2741 +18138 +2456 +16540 +12104 +11443 +1298 +2118 +17615 +5995 +6862 +3488 +15526 +11304 +4840 +8637 +15790 +775 +1137 +8983 +18397 +9798 +722 +5346 +15242 +12505 +15983 +19275 +15580 +13633 +13717 +11944 +12196 +10522 +13473 +2644 +10497 +17461 +17569 +6378 +8597 +16327 +1211 +4162 +6847 +4340 +19951 +1599 +7135 +15964 +5626 +14662 +11134 +5105 +12657 +17545 +3080 +18801 +11012 +16064 +4083 +2642 +18572 +977 +12963 +1483 +9630 +11837 +71 +10721 +3758 +18526 +10761 +8113 +4746 +9448 +3092 +16557 +17825 +18446 +8252 +392 +18106 +2957 +14830 +13937 +13308 +3804 +755 +7778 +17863 +8619 +13266 +17882 +16879 +19924 +11389 +11255 +14986 +15788 +1779 +7856 +19252 +11341 +805 +3380 +9491 +5805 +10094 +15694 +17089 +3040 +11579 +3307 +15278 +10400 +6058 +9593 +13908 +17052 +7700 +4979 +11938 +16412 +18864 +4819 +12537 +4342 +8687 +12683 +12049 +13008 +15497 +992 +6943 +19289 +12947 +1456 +14316 +8409 +16042 +13950 +13145 +14558 +14961 +10435 +15751 +2927 +15037 +13411 +13988 +16928 +12420 +14982 +3404 +15797 +14812 +19720 +11288 +1366 +4130 +9898 +998 +14385 +2657 +12093 +18980 +12937 +15151 +224 +10603 +2698 +3295 +6210 +10846 +11517 +11958 +7695 +9031 +2278 +17046 +15210 +7702 +11565 +2208 +877 +14359 +14139 +14411 +9053 +12569 +5575 +14752 +6876 +10816 +9560 +3562 +3894 +11237 +12842 +3335 +17299 +5688 +16983 +12775 +8516 +18919 +5076 +6027 +11966 +18406 +13103 +18220 +7896 +14930 +1302 +8829 +8453 +314 +10673 +4087 +7300 +19948 +800 +10413 +8825 +11842 +17749 +8810 +4490 +17681 +836 +12925 +11007 +9020 +5874 +9433 +7709 +8667 +4530 +1106 +9895 +17803 +16113 +8158 +1187 +19264 +6286 +19216 +16332 +2287 +19260 +15395 +17989 +17056 +4257 +6020 +12588 +11996 +9770 +6531 +5827 +1785 +12064 +10807 +10294 +19059 +4504 +15596 +6438 +4825 +7552 +9057 +18677 +8279 +17911 +19664 +4538 +17226 +19027 +9047 +17028 +14974 +14105 +2303 +11840 +9568 +10111 +3082 +10249 +13152 +5532 +14213 +16516 +18014 +19653 +8949 +10972 +14520 +16575 +3656 +14027 +15027 +9694 +12890 +10080 +18771 +16314 +10556 +12661 +19972 +18649 +699 +13948 +7751 +3131 +6784 +2676 +275 +2888 +16062 +7163 +19120 +12723 +17616 +18763 +10595 +15530 +2995 +783 +13107 +3416 +8081 +8176 +17959 +1728 +10932 +19737 +12468 +15440 +10682 +10281 +10498 +11967 +9314 +9189 +11332 +17661 +18196 +14557 +786 +17267 +8999 +4686 +1022 +7812 +18280 +456 +4312 +10302 +2906 +8606 +19544 +14775 +730 +16858 +19191 +6550 +13128 +17408 +18023 +9971 +19711 +11312 +4487 +4085 +15128 +14255 +8297 +18539 +787 +331 +6999 +12733 +10978 +14555 +16517 +15097 +8241 +3234 +15937 +13922 +17459 +1870 +17768 +14584 +19259 +5116 +5727 +931 +3767 +8005 +2607 +11446 +16883 +13893 +17149 +6018 +13261 +19066 +4685 +13725 +10893 +8622 +19603 +3692 +7888 +10635 +14670 +14441 +16672 +10622 +10074 +11786 +2699 +19206 +8367 +18976 +3421 +10434 +4451 +7403 +3857 +1799 +13049 +18178 +8514 +10714 +6771 +3152 +18337 +10109 +1083 +8326 +19805 +5950 +19847 +4527 +5855 +11501 +19808 +6397 +15479 +19244 +4186 +2528 +12598 +7043 +17510 +15752 +11162 +6982 +6216 +6264 +13484 +2039 +19015 +2433 +2694 +1544 +8215 +10538 +16695 +118 +16077 +11429 +1496 +11057 +13818 +14005 +12615 +5221 +12602 +3674 +301 +14175 +13343 +600 +14983 +524 +820 +15281 +11539 +4133 +4198 +19963 +5947 +10165 +15234 +11491 +4135 +4983 +1876 +7528 +7304 +1562 +15212 +1043 +19677 +4850 +16854 +8897 +18780 +14903 +3881 +5463 +5893 +15405 +16276 +1209 +13525 +6806 +10732 +7767 +13288 +15528 +6372 +12709 +6129 +12409 +9811 +18287 +2895 +15777 +401 +3278 +8573 +1554 +6500 +15252 +13647 +11399 +2242 +12502 +12507 +3477 +17207 +10341 +15525 +4823 +9161 +6308 +13294 +10629 +16245 +3296 +3538 +2801 +10584 +9403 +12498 +8714 +5198 +1338 +19990 +3574 +7314 +16620 +7569 +3494 +1 +14065 +3145 +17457 +9284 +7180 +10892 +7111 +8180 +1821 +2014 +16794 +19005 +12917 +8470 +17343 +1518 +7529 +6587 +11100 +1760 +16159 +6964 +19509 +8222 +11116 +15229 +13559 +6183 +709 +2098 +15239 +6169 +19667 +17363 +13213 +3144 +10767 +11387 +5134 +2003 +12185 +19682 +9113 +4577 +19384 +8926 +537 +11326 +11783 +16912 +4178 +16291 +10344 +17866 +5561 +2746 +10562 +11578 +5294 +14800 +19925 +12412 +15835 +11577 +9481 +14515 +17350 +14493 +7078 +6986 +18146 +9531 +16411 +5954 +2511 +5791 +11662 +13463 +14537 +6179 +2025 +4119 +6428 +7919 +12301 +741 +17003 +11520 +2322 +18545 +2816 +5994 +6105 +16107 +1073 +14622 +13342 +18050 +10078 +17345 +17554 +1543 +18 +7660 +5438 +9943 +3594 +3703 +5395 +11370 +16581 +15418 +3400 +10412 +14131 +13197 +13665 +12372 +18872 +12839 +2460 +16996 +12585 +13902 +15263 +9686 +16563 +1457 +13276 +947 +3589 +1135 +18197 +11713 +12163 +2204 +2919 +9626 +16423 +15582 +15949 +4205 +17938 +17413 +19576 +4993 +5283 +14579 +5309 +14546 +15726 +2849 +2142 +11410 +13810 +9479 +3820 +866 +9978 +16784 +11671 +6837 +16320 +11812 +12184 +8153 +6873 +7419 +7101 +3344 +19846 +9263 +1478 +10669 +12194 +4501 +10924 +7264 +13394 +18353 +1956 +1277 +12092 +12460 +5232 +19324 +2119 +16437 +9390 +11362 +7475 +2597 +15271 +10529 +6995 +19228 +4045 +4951 +8139 +4466 +18481 +4561 +16783 +10099 +6860 +17063 +927 +2033 +12648 +17781 +2898 +1320 +9871 +6326 +17469 +10601 +14705 +9870 +19192 +7219 +8847 +2792 +15438 +6422 +12590 +11420 +2627 +6361 +18901 +19204 +16903 +15181 +11050 +18231 +2536 +1986 +9228 +19402 +2165 +6001 +7311 +4519 +11158 +16208 +13691 +1942 +7375 +6005 +19039 +12972 +16462 +12515 +9276 +6880 +11200 +9931 +5623 +2862 +9716 +50 +9944 +8391 +12853 +11878 +7254 +15717 +14919 +19413 +7322 +4016 +2527 +16907 +2524 +5135 +17276 +10647 +13279 +10015 +9776 +12604 +3113 +16471 +14999 +11702 +19608 +10787 +8154 +5807 +13462 +604 +8939 +6273 +8979 +12619 +10386 +13069 +15727 +11689 +4536 +16075 +13938 +13580 +15599 +18962 +10735 +11802 +10383 +1399 +4410 +3535 +17480 +14985 +2814 +3123 +2724 +6224 +18865 +8240 +17731 +19163 +11893 +3245 +12224 +10103 +2013 +3435 +5017 +19932 +18568 +2339 +13 +3243 +17153 +10233 +4851 +2574 +17494 +10453 +8242 +9960 +372 +3410 +11084 +5357 +9627 +3896 +12304 +15424 +4673 +3841 +3832 +17147 +8123 +13614 +19935 +18746 +8343 +2887 +11414 +2347 +7245 +589 +13837 +5735 +18374 +5222 +2040 +10839 +15184 +16493 +1697 +8528 +3958 +15919 +14802 +14478 +12316 +47 +3814 +15941 +17556 +5025 +6505 +2599 +4807 +16573 +9026 +4753 +13330 +17961 +6951 +4176 +18581 +6280 +482 +7481 +847 +5703 +6686 +12430 +9343 +15955 +14406 +1063 +5293 +1944 +10734 +14286 +17833 +9802 +6627 +4307 +11310 +7206 +4848 +13644 +17175 +11330 +4675 +8977 +15247 +14724 +535 +16143 +3270 +4548 +6938 +6677 +9005 +7020 +9088 +15010 +17070 +704 +119 +12456 +15356 +13788 +9116 +7416 +237 +15198 +59 +13761 +10205 +9325 +10372 +1454 +12134 +17095 +13936 +11049 +502 +4606 +6182 +3863 +15307 +4583 +11554 +15812 +14138 +3258 +6628 +2885 +16888 +641 +11710 +5554 +14854 +9242 +16270 +11171 +19856 +18552 +15074 +17754 +2806 +7711 +4314 +19993 +3468 +12255 +6787 +15711 +7231 +4434 +10023 +9285 +5031 +19987 +13934 +12706 +5672 +9465 +7875 +10303 +19459 +4489 +6807 +6819 +11240 +5921 +12952 +3370 +9733 +10462 +12708 +4175 +5746 +5906 +4485 +10783 +12094 +9690 +18895 +10977 +880 +15847 +8134 +7030 +2154 +18109 +13728 +5571 +11363 +13663 +4131 +8656 +10532 +14433 +17810 +15439 +17251 +4456 +14559 +17505 +1586 +8790 +12115 +3177 +6671 +670 +8561 +17786 +18107 +16930 +14761 +1432 +5153 +6021 +111 +14955 +4624 +16076 +14237 +9844 +1270 +17917 +17015 +15227 +19331 +18072 +7003 +1960 +10914 +6799 +15138 +15068 +13651 +19053 +8900 +16740 +12291 +2503 +5685 +6639 +8718 +7792 +8309 +12079 +45 +84 +13028 +19830 +17453 +10848 +18701 +3321 +2212 +8817 +19290 +19602 +3811 +13789 +144 +7167 +7729 +2717 +6197 +13454 +13704 +14757 +17324 +15910 +9469 +14907 +4555 +708 +1123 +7625 +13782 +13126 +17596 +13957 +9220 +6709 +8019 +11503 +2173 +4388 +16776 +7399 +18430 +6831 +4496 +642 +7723 +5530 +19442 +3778 +2952 +11253 +8700 +5520 +4446 +12978 +1215 +7685 +9872 +15951 +3934 +9149 +1390 +2471 +12160 +14399 +2434 +18415 +1218 +32 +7982 +6812 +4124 +16855 +18941 +2465 +2734 +16235 +6157 +11791 +2737 +4717 +6371 +13109 +7912 +11730 +3555 +16654 +6456 +15368 +7580 +8096 +10407 +14311 +10043 +14424 +369 +12222 +930 +11154 +10068 +4544 +5456 +19536 +4857 +17200 +8804 +13532 +8733 +422 +1506 +18343 +14719 +14153 +3048 +10267 +14506 +5029 +19942 +5898 +2382 +3445 +9501 +18362 +15809 +12221 +17889 +1979 +2217 +16234 +5817 +10847 +16634 +18902 +1743 +4247 +8945 +19623 +10002 +4438 +12048 +6623 +9521 +13864 +17763 +9245 +17975 +11607 +1909 +17851 +10919 +18575 +9464 +10642 +6247 +2061 +18940 +6649 +2106 +14928 +9727 +5719 +8118 +11365 +19383 +4681 +1252 +5370 +9341 +932 +19183 +2420 +11824 +15570 +3993 +15431 +12494 +6548 +16249 +9922 +8387 +17677 +1629 +11720 +3636 +16336 +14087 +8133 +3755 +960 +3946 +16751 +8827 +4885 +11718 +17113 +2463 +17058 +2197 +11153 +17542 +13968 +1692 +9510 +1598 +17488 +19609 +3440 +173 +1849 +6383 +13880 +5226 +8374 +7870 +4086 +12667 +7468 +6736 +10201 +2125 +2589 +6608 +5270 +7683 +3717 +14243 +10644 +11638 +1189 +8767 +19540 +9812 +3980 +13301 +13319 +16386 +14660 +6190 +19137 +18090 +6845 +9849 +7178 +9816 +308 +9653 +11880 +4949 +1903 +7656 +2818 +15129 +13426 +14721 +12555 +7133 +9304 +1140 +5193 +17641 +19302 +2755 +9232 +2290 +12070 +14373 +18000 +6573 +1429 +18199 +12099 +9266 +19799 +19842 +14630 +15890 +5400 +1168 +1334 +678 +6820 +19767 +9867 +3627 +15482 +4219 +18098 +11759 +6569 +1522 +5971 +14975 +19122 +3102 +10832 +14152 +15486 +11430 +14481 +10335 +3613 +19350 +4041 +3053 +8884 +8173 +14611 +5180 +9204 +3476 +18133 +7054 +15400 +17218 +2182 +5252 +13778 +10306 +8472 +17474 +13635 +15264 +8964 +19173 +13839 +5596 +12642 +2008 +6478 +4278 +10186 +6869 +984 +4803 +3481 +18944 +14282 +13615 +15811 +19363 +11136 +7189 +15192 +1759 +3303 +7237 +13518 +11633 +14817 +14946 +16346 +5785 +4870 +8768 +4729 +14672 +13143 +12444 +7398 +14648 +16298 +8079 +14285 +7397 +14078 +13859 +4581 +14442 +16714 +9176 +8370 +188 +12186 +11185 +2192 +556 +6540 +17373 +7988 +7629 +8772 +15852 +1841 +7050 +3644 +1975 +16088 +10223 +3437 +5406 +398 +9409 +8221 +11022 +4599 +17923 +19212 +8525 +13827 +13178 +13063 +13568 +597 +8534 +12787 +9439 +12550 +17022 +7335 +4231 +14528 +17725 +4976 +14923 +15675 +12650 +747 +13745 +4043 +10501 +10969 +4941 +4153 +2195 +12187 +11124 +447 +15401 +18301 +10561 +6296 +1363 +3414 +12037 +4513 +9714 +4258 +4202 +1567 +9251 +3195 +2028 +13727 +10188 +17434 +5451 +393 +10472 +18208 +5378 +3288 +15950 +3389 +16984 +10052 +7082 +1509 +16150 +11193 +3482 +18241 +15206 +12694 +8589 +19453 +14117 +8083 +18296 +15671 +903 +16727 +14083 +19159 +10439 +493 +5493 +17086 +15611 +1575 +16574 +11052 +2315 +19831 +1676 +14627 +19279 +9199 +7674 +5230 +15390 +15977 +19765 +11356 +12465 +18800 +5462 +2300 +8322 +4146 +16519 +16998 +4393 +7958 +3184 +13159 +2890 +1996 +14181 +637 +13125 +13038 +3623 +3067 +11766 +12208 +5955 +12813 +16951 +8522 +3119 +15340 +19563 +19939 +4996 +19335 +1037 +18714 +17876 +18389 +13231 +15917 +7782 +14898 +18670 +11630 +17753 +8603 +3584 +10272 +18520 +19060 +15779 +6553 +2105 +3022 +6160 +11143 +15697 +13675 +220 +13874 +6529 +13783 +8706 +1262 +10317 +12012 +12435 +18774 +19300 +1419 +11201 +16096 +12869 +4769 +14310 +1364 +16991 +6117 +2631 +6040 +3103 +6942 +11453 +7901 +6972 +14364 +12145 +417 +9965 +12878 +2626 +17576 +19338 +15036 +13574 +12971 +12247 +13085 +2336 +19684 +5237 +5187 +11919 +562 +13007 +16523 +12939 +5250 +5588 +16600 +10405 +9663 +12558 +19723 +16362 +8135 +19763 +9391 +2427 +7476 +2029 +18293 +15895 +2385 +1489 +636 +981 +1156 +13282 +15115 +9598 +1213 +16544 +1296 +15737 +2784 +5932 +11104 +13888 +2530 +9706 +11081 +3524 +8956 +13166 +18557 +6065 +163 +6033 +516 +18459 +16866 +11518 +5428 +478 +11492 +10280 +7532 +7002 +14327 +3220 +14828 +7036 +16393 +13768 +2930 +1117 +6726 +2318 +13211 +4689 +3342 +10203 +12398 +16526 +8782 +4418 +8237 +3169 +19441 +10112 +18812 +13734 +4102 +17219 +5543 +1906 +14728 +19262 +15429 +7648 +7893 +17037 +4627 +16891 +11123 +5327 +6657 +2501 +1812 +13229 +3099 +3375 +5468 +3815 +4459 +860 +11151 +4140 +15652 +11792 +7192 +1686 +19348 +13925 +19637 +7427 +18068 +2010 +13216 +10431 +17501 +17030 +9687 +18018 +13730 +19817 +18679 +8473 +10827 +341 +4169 +1846 +9755 +14042 +1180 +13438 +7194 +15654 +9099 +15454 +12018 +19197 +1755 +4150 +15169 +10857 +6352 +7006 +10408 +13355 +19450 +15119 +7004 +257 +10915 +6684 +8840 +18930 +4641 +10877 +229 +7166 +9896 +5905 +7545 +344 +15920 +9152 +246 +9058 +19520 +4300 +4792 +19691 +3504 +817 +8737 +12905 +2415 +6907 +8860 +5027 +8024 +3888 +16163 +11647 +14006 +12023 +4877 +7644 +1563 +11462 +18219 +12019 +1989 +8497 +6763 +3996 +181 +11278 +11703 +554 +6004 +16785 +5024 +17144 +11675 +2857 +2485 +13659 +17741 +11130 +12704 +19747 +6166 +778 +6670 +19756 +8796 +19227 +385 +10731 +11961 +4047 +15990 +19669 +12521 +16944 +16474 +13432 +10829 +6960 +19887 +2559 +18752 +8361 +13833 +17824 +13186 +8008 +10746 +9302 +12298 +19491 +17194 +94 +2726 +9562 +17936 +14229 +17211 +1264 +2388 +7536 +9309 +1090 +4704 +2987 +16669 +1069 +5974 +666 +4110 +12960 +7011 +3430 +3658 +7957 +13867 +2305 +6814 +9642 +18184 +6066 +10263 +6331 +6583 +11401 +18710 +7761 +9120 +18732 +7057 +15086 +13461 +9607 +620 +357 +10244 +16750 +12518 +14047 +13311 +1637 +8493 +9688 +3472 +12299 +5998 +13924 +6504 +7669 +1921 +9307 +3126 +6080 +18350 +17884 +19096 +19377 +1765 +3605 +16444 +6057 +19150 +7336 +745 +12446 +18967 +17715 +954 +6207 +12627 +3154 +11384 +14172 +15881 +10026 +2786 +18142 +18848 +14487 +19946 +14489 +12259 +1326 +10541 +1739 +7035 +13278 +10706 +1226 +352 +7017 +19211 +1966 +5756 +19780 +18829 +34 +11245 +2462 +4457 +14180 +2692 +14910 +13246 +6710 +10638 +7946 +7282 +8727 +1368 +3519 +5185 +6794 +8042 +5645 +5808 +4835 +17102 +3921 +11209 +12136 +10628 +3576 +4998 +7242 +18183 +4817 +1796 +6850 +16380 +8288 +16177 +12374 +2774 +12953 +19135 +17368 +12202 +2671 +12030 +3502 +13272 +18318 +2947 +9429 +17981 +13291 +16647 +9353 +13506 +1345 +1606 +17865 +15331 +3223 +9213 +2329 +6693 +15916 +2748 +1597 +12141 +14140 +10183 +17864 +15681 +10661 +17526 +3179 +2682 +9129 +17455 +9142 +7890 +908 +4428 +1257 +6910 +4718 +19099 +15214 +168 +15250 +19414 +6957 +7013 +3617 +15080 +2637 +19908 +7213 +2778 +8424 +6742 +13447 +1388 +8942 +6449 +13283 +6520 +14973 +1632 +9919 +3172 +10166 +15706 +1954 +12442 +6048 +265 +884 +19234 +2575 +19868 +18708 +1191 +3020 +14077 +15453 +1936 +2761 +13577 +17654 +9508 +15423 +12865 +3808 +2055 +13652 +5522 +8046 +17315 +11752 +2304 +4058 +7626 +9317 +10968 +6605 +18609 +12029 +9514 +12933 +6311 +6106 +4719 +10381 +6532 +12583 +14195 +11685 +4255 +15557 +6704 +15840 +15208 +6497 +8632 +3696 +7840 +12973 +18856 +9969 +19613 +18563 +6743 +13422 +6575 +12637 +3962 +14827 +1112 +19268 +5240 +5901 +13009 +5481 +15268 +13265 +16451 +18319 +1837 +8355 +8598 +4207 +983 +12961 +13919 +14456 +1836 +1239 +3682 +2158 +15971 +12416 +17843 +12431 +5091 +2773 +11993 +10113 +10676 +17265 +115 +11344 +13027 +6813 +17885 +15398 +5191 +16829 +7964 +13565 +2469 +15284 +15334 +15636 +16577 +17943 +13522 +13595 +15555 +2598 +17872 +10530 +17790 +5792 +4328 +19037 +4015 +14635 +1783 +3928 +17277 +10138 +10764 +21 +7171 +5579 +2956 +15658 +4832 +9159 +12366 +2086 +1677 +1346 +13813 +14918 +19250 +3229 +5583 +15552 +17391 +19445 +19064 +19222 +8963 +10540 +14799 +9 +11515 +12578 +13606 +8198 +18794 +4379 +3132 +19960 +18979 +631 +5846 +12072 +15204 +5022 +7193 +12746 +8665 +4090 +8310 +4594 +11466 +15411 +13457 +5418 +16502 +10360 +13018 +1912 +2683 +19853 +2078 +3221 +17284 +6288 +14554 +7948 +16763 +3317 +3633 +3568 +6613 +16070 +17081 +15908 +12464 +8082 +13060 +2555 +3439 +8477 +12271 +5038 +19860 +4829 +11706 +7998 +8384 +1595 +1805 +1640 +474 +14984 +3614 +10814 +14329 +419 +4940 +10881 +9506 +13006 +10918 +8530 +17562 +5725 +17235 +1167 +17756 +462 +11525 +8492 +2843 +6761 +11361 +6935 +11226 +8856 +16721 +17026 +57 +5769 +14925 +9033 +10129 +2837 +8439 +1616 +6434 +11611 +14205 +6075 +11770 +5291 +2326 +7364 +586 +12935 +14640 +9955 +335 +18730 +1813 +11972 +4690 +672 +5793 +13220 +5178 +13492 +19396 +15145 +8657 +11858 +19994 +19162 +1033 +7147 +2330 +19757 +572 +643 +384 +9925 +1125 +16239 +1468 +14128 +11184 +17656 +19701 +15014 +2804 +19155 +18053 +16216 +4912 +17608 +12940 +9707 +16399 +9962 +1229 +2002 +9092 +4211 +14353 +15441 +18468 +9370 +16688 +987 +9588 +8286 +7260 +40 +2980 +12044 +3622 +16853 +6776 +1292 +11037 +14858 +11338 +3271 +6792 +5869 +17176 +4935 +9850 +3133 +530 +5284 +11481 +15789 +14037 +1792 +10600 +16448 +16402 +7271 +10259 +18759 +8559 +16204 +16052 +3246 +12904 +15531 +10970 +4450 +483 +12566 +15607 +588 +15992 +5443 +1447 +12752 +2411 +166 +19825 +16716 +6513 +18826 +12041 +10452 +16902 +829 +4188 +4493 +3208 +17099 +18648 +13847 +8111 +18607 +13743 +18881 +3827 +6130 +4139 +4965 +6177 +10051 +12253 +13041 +9234 +18908 +8614 +1776 +14967 +18358 +3366 +11589 +413 +18726 +18555 +17591 +2060 +8879 +3791 +18548 +2665 +7895 +15282 +19893 +2338 +14473 +11013 +207 +13584 +19911 +18401 +16144 +13453 +5700 +10181 +13519 +4557 +16640 +10933 +8755 +6884 +10786 +8921 +8348 +8360 +3935 +7072 +11688 +18657 +16435 +16612 +9620 +15485 +12302 +1287 +4750 +17816 +6462 +19313 +13429 +10803 +19658 +1811 +2333 +2788 +12509 +2391 +13374 +756 +10119 +526 +11502 +4846 +16478 +6897 +18228 +14718 +9334 +1484 +16094 +14722 +17019 +15695 +18441 +11231 +12369 +6240 +9002 +3631 +615 +7153 +4790 +10958 +17839 +10995 +9926 +6795 +12125 +1982 +4400 +9387 +1529 +5381 +18595 +17504 +2169 +4636 +2246 +18988 +17023 +11444 +16361 +13146 +17374 +14877 +18345 +300 +18462 +12824 +564 +134 +17523 +1134 +2452 +1038 +18878 +5092 +18926 +451 +11879 +15764 +13985 +5625 +8596 +12546 +12755 +10421 +3777 +10152 +11441 +19910 +12031 +16841 +7655 +10693 +5392 +18506 +12563 +18995 +15619 +11364 +14263 +13044 +12997 +13346 +13160 +11672 +17259 +2736 +319 +9151 +10928 +1832 +7854 +15517 +3459 +2878 +17775 +19969 +6304 +18289 +37 +7244 +13589 +3371 +8941 +13784 +7754 +5591 +89 +18899 +16011 +1249 +7622 +8592 +16098 +7570 +12850 +7579 +13637 +6854 +11655 +14479 +3180 +18981 +19456 +4523 +10036 +504 +8811 +12882 +14072 +4101 +602 +1818 +8398 +2965 +4771 +14349 +619 +3381 +9045 +17723 +11003 +551 +11987 +6641 +10576 +5382 +4609 +2232 +7400 +14606 +17782 +1882 +11952 +12883 +1013 +1045 +2239 +4588 +12565 +9769 +15195 +15723 +19314 +14132 +8295 +942 +5104 +16908 +10156 +4667 +13361 +13593 +17199 +17751 +15670 +16848 +4233 +7844 +13082 +18753 +16815 +5325 +9544 +18949 +15867 +18450 +1523 +13507 +3925 +9375 +8022 +16922 +19002 +18483 +6997 +9114 +869 +6463 +18983 +1099 +7611 +15944 +19025 +11257 +19088 +16057 +4747 +3210 +12362 +8623 +553 +7619 +8730 +13142 +12287 +17628 +5674 +2143 +2667 +19194 +14067 +14994 +5916 +6983 +11142 +18968 +9128 +234 +16008 +13918 +14901 +8770 +7161 +7706 +8783 +4742 +7058 +16184 +14926 +1098 +2953 +13416 +9591 +13168 +6290 +2187 +13489 +12669 +3316 +1603 +14778 +11423 +17530 +11102 +13092 +10690 +11992 +15793 +7483 +3486 +14589 +17624 +3801 +13150 +6451 +9171 +17302 +4744 +12516 +7190 +17853 +17486 +15132 +575 +16293 +10909 +19815 +7396 +16384 +18258 +4260 +9017 +1057 +418 +15588 +18699 +7408 +1669 +9855 +17928 +4332 +19007 +7179 +7097 +10636 +8254 +15571 +17880 +17858 +2467 +4824 +8630 +5507 +7748 +13207 +7708 +9601 +13215 +9756 +16026 +7734 +12007 +3985 +3975 +24 +8499 +19781 +16997 +19931 +7498 +18003 +898 +3774 +5267 +19904 +1141 +3236 +3997 +340 +8277 +10219 +19621 +9143 +17010 +11669 +12691 +8169 +9079 +14583 +14459 +12061 +11205 +14789 +3757 +4913 +4123 +1307 +687 +8143 +5783 +6087 +3116 +6893 +18700 +1126 +18939 +14849 +19168 +13694 +3354 +4732 +7220 +9715 +2729 +9476 +7883 +3283 +18448 +7298 +19525 +6913 +10908 +17048 +9894 +3151 +1736 +12383 +4842 +18693 +11914 +7090 +7865 +5521 +4669 +12482 +19952 +8529 +15462 +2518 +327 +10523 +1055 +13857 +19428 +11179 +2896 +15066 +11934 +935 +4289 +11899 +568 +1028 +3057 +1623 +12628 +9328 +9278 +19555 +8131 +10592 +16847 +11519 +4304 +18582 +5299 +2381 +2830 +3465 +14862 +2112 +3199 +15457 +9221 +15445 +6534 +10946 +1244 +4061 +14787 +19829 +10695 +19455 +5951 +3522 +14155 +18282 +4454 +13337 +16782 +9130 +8003 +1143 +6838 +6755 +16851 +6626 +15090 +5895 +18185 +9123 +19638 +11475 +1588 +5718 +8144 +12244 +7806 +9909 +13328 +12618 +16186 +14803 +3571 +1175 +6242 +13141 +4981 +16953 +15739 +15888 +15825 +8584 +12073 +12181 +6668 +13546 +17247 +7490 +5641 +18695 +17270 +19130 +15593 +9991 +8480 +19426 +17306 +3868 +2172 +4648 +16842 +7443 +12297 +16167 +16153 +8206 +17653 +16223 +18306 +8011 +13258 +8749 +11413 +17355 +18821 +2392 +7736 +1065 +3762 +11127 +13274 +14848 +7261 +11626 +14264 +10701 +9139 +6803 +7406 +16136 +15216 +18770 +8147 +10579 +5432 +1354 +10479 +8928 +13710 +2474 +11118 +13383 +15609 +5990 +19489 +15815 +8567 +16068 +2522 +3666 +11847 +16138 +7991 +12520 +15287 +18644 +4712 +9022 +14031 +1952 +10045 +2917 +13650 +2881 +19104 +3556 +5163 +6530 +16196 +3566 +9300 +5245 +2996 +18038 +2647 +3943 +13251 +13680 +17217 +1077 +6341 +15865 +1918 +437 +4834 +2572 +7862 +5711 +8408 +8924 +3418 +19594 +13314 +16731 +18513 +3075 +19643 +11476 +18781 +11249 +16940 +13425 +8467 +10608 +5912 +4692 +6496 +17159 +18817 +9774 +17707 +10887 +2646 +3101 +15565 +13814 +7910 +10234 +7672 +18593 +16125 +3872 +4688 +13502 +15285 +10258 +15956 +16674 +17513 +16734 +18127 +283 +16584 +3550 +2235 +19977 +4930 +2725 +2122 +13871 +5420 +13472 +5896 +17210 +9381 +2334 +15279 +7181 +3162 +10175 +2835 +6150 +13023 +1663 +5737 +5310 +2815 +7940 +12773 +16395 +11629 +15496 +2439 +17094 +5132 +3999 +17160 +10801 +3114 +4724 +1838 +4275 +19750 +10670 +7456 +12380 +15744 +14920 +4978 +5790 +9529 +8616 +12128 +4683 +6244 +1403 +3531 +360 +13158 +11178 +1997 +14972 +3992 +1034 +10672 +5935 +5578 +19888 +6243 +6653 +2371 +9222 +18521 +2413 +16275 +785 +3406 +16603 +9376 +4375 +12899 +17609 +8678 +13468 +16027 +14774 +14184 +3171 +2946 +15157 +6421 +18315 +18057 +13759 +14435 +17583 +11371 +4966 +15100 +1712 +8162 +13435 +7357 +11300 +17969 +16426 +13370 +6748 +10065 +6604 +5001 +9209 +3874 +14068 +5079 +14734 +434 +6630 +6747 +1394 +1085 +4425 +3478 +2053 +1367 +1025 +1560 +7981 +7309 +993 +15315 +9454 +7358 +11342 +7099 +7703 +12000 +4024 +14266 +9311 +2993 +15389 +19584 +18740 +8699 +11727 +6541 +11947 +3186 +7348 +13898 +693 +3189 +3074 +2425 +18658 +3065 +2567 +12010 +16450 +13757 +13022 +14769 +14444 +15466 +17832 +8016 +7075 +9185 +4847 +16771 +10268 +9578 +6919 +19624 +13031 +13380 +5124 +13554 +15078 +19046 +470 +3930 +655 +4019 +8440 +19527 +194 +9411 +9840 +7478 +6682 +4887 +4617 +17055 +759 +16034 +14466 +684 +16571 +2455 +16807 +6394 +5985 +15965 +10079 +2847 +13081 +7466 +15162 +17571 +13721 +6698 +11339 +14030 +14447 +10426 +13351 +8454 +18388 +4572 +13310 +13512 +6676 +2730 +18079 +15177 +895 +14003 +16172 +3572 +14307 +7807 +8842 +3323 +6491 +8751 +18445 +7376 +1592 +7774 +18987 +9532 +12636 +8777 +7540 +4054 +17548 +16481 +19598 +19357 +6078 +9000 +11767 +190 +2819 +17894 +3474 +4462 +13444 +8448 +15973 +10837 +13252 +12071 +15238 +5285 +7605 +7234 +7421 +8906 +11564 +1479 +14953 +19400 +5465 +15855 +2019 +16192 +10889 +8776 +15519 +6817 +345 +16653 +13688 +2403 +14018 +16537 +19797 +19997 +4634 +14400 +8655 +9483 +18683 +13841 +9504 +16741 +5014 +2577 +4225 +9013 +14064 +16518 +10623 +387 +17050 +6189 +999 +12600 +13726 +5888 +6007 +11479 +16718 +12795 +19897 +16182 +18458 +13772 +7673 +19890 +7047 +5618 +5959 +7185 +15330 +2138 +8591 +2605 +7691 +18431 +9186 +17634 +15342 +11687 +919 +8615 +10055 +2690 +11161 +2548 +10916 +8538 +5012 +1559 +5083 +8487 +2702 +18625 +9752 +6730 +11701 +10378 +7582 +5144 +16250 +17020 +18819 +17867 +2077 +10760 +6501 +16111 +5174 +1236 +8417 +15243 +15428 +4185 +17971 +11150 +2270 +4076 +10418 +9616 +14304 +9739 +14354 +11173 +9077 +2553 +17544 +16796 +7414 +5750 +16219 +11777 +3621 +12054 +6991 +4516 +3866 +13047 +17679 +2416 +13399 +337 +14655 +18382 +16054 +18064 +17422 +17215 +17498 +1750 +7126 +3127 +18565 +6762 +18960 +10966 +6662 +6082 +3070 +15563 +12371 +7905 +4700 +11434 +3014 +18514 +12815 +17114 +14966 +3384 +2723 +12173 +291 +1462 +3643 +17993 +1139 +7562 +8067 +8759 +8205 +14015 +3287 +1738 +10139 +1963 +15196 +7513 +5494 +15932 +17383 +6751 +7542 +5886 +15038 +3784 +2253 +7851 +2779 +12151 +7157 +19881 +11373 +17650 +174 +4010 +5259 +18803 +11562 +7188 +11876 +17734 +6949 +10287 +14157 +18143 +8517 +1622 +16646 +6088 +12780 +5103 +3603 +13777 +11604 +16943 +2542 +4967 +1369 +6433 +11825 +12008 +6494 +7531 +15518 +11926 +1104 +18507 +2332 +2257 +4511 +1230 +7978 +958 +10757 +4564 +15232 +5841 +6680 +10704 +17564 +15669 +5712 +2926 +3964 +3324 +15679 +15296 +5331 +3663 +1717 +17708 +5943 +11395 +16378 +5660 +4341 +1166 +17091 +1582 +6016 +216 +18784 +4639 +17240 +18603 +3597 +6350 +17348 +12607 +10364 +3058 +10709 +7744 +2871 +6905 +4195 +17230 +6343 +10021 +16126 +15597 +17983 +5405 +16319 +885 +15877 +14568 +3527 +7602 +13623 +1531 +14019 +12641 +157 +4128 +2733 +12364 +18822 +1283 +15255 +8284 +11428 +4062 +15606 +7132 +16755 +2863 +16252 +17191 +10100 +10459 +13758 +13200 +3710 +7159 +13800 +15040 +5271 +6711 +13654 +9837 +5173 +19220 +10368 +11398 +6330 +4006 +12476 +6586 +5797 +4242 +15703 +1665 +8427 +14178 +5244 +1968 +5818 +12107 +15505 +13285 +11529 +8822 +6603 +16260 +19339 +7627 +5654 +14824 +4389 +17580 +12135 +3680 +889 +10104 +15702 +13504 +1214 +7198 +19579 +15374 +12365 +12999 +11772 +14776 +9617 +6293 +9577 +13967 +18943 +16729 +7577 +14436 +19298 +6622 +10665 +8431 +19395 +19984 +10662 +14632 +16580 +16368 +12239 +6318 +13228 +8861 +7813 +6366 +1645 +13066 +2491 +11844 +15839 +12306 +14755 +19548 +18460 +2393 +5422 +364 +17185 +7575 +16636 +4921 +11833 +3376 +3818 +3752 +5026 +14107 +18861 +19157 +9505 +271 +17577 +2479 +9984 +2376 +15784 +14631 +6083 +957 +3039 +15020 +18999 +1508 +6772 +10931 +17855 +6992 +19287 +12666 +14170 +1740 +12923 +6858 +2309 +9440 +18070 +2886 +10054 +15402 +4626 +4196 +9897 +5702 +13410 +8233 +12649 +590 +19261 +238 +1938 +12592 +12402 +11487 +1732 +3452 +1752 +6939 +9524 +16769 +9060 +1911 +5708 +2742 +697 +13692 +17972 +10130 +12765 +6963 +1276 +7169 +9722 +3860 +9525 +6254 +5355 +8312 +12798 +8280 +1371 +18400 +15762 +1407 +4048 +9087 +15999 +2369 +6100 +7596 +1131 +19386 +3638 +1032 +12675 +18835 +812 +6274 +17032 +386 +2167 +3678 +10792 +13541 +10961 +7152 +18589 +11442 +7770 +2065 +9704 +5282 +6167 +16058 +5089 +18413 +6249 +8785 +1896 +171 +5035 +12241 +1190 +17145 +7144 +17135 +8142 +9241 +4830 +18909 +2636 +14302 +8987 +18964 +17752 +12531 +19686 +16553 +8709 +14063 +12538 +7511 +10082 +2968 +1893 +12781 +13845 +2048 +10552 +6937 +9259 +15372 +4901 +10380 +240 +19041 +17426 +9757 +244 +13914 +2372 +3036 +6899 +4460 +14836 +11513 +98 +2310 +12522 +7953 +531 +19399 +19557 +6452 +18372 +2159 +15351 +4288 +2639 +8950 +7120 +3454 +14580 +19091 +13984 +8855 +8837 +5926 +13956 +9366 +15757 +12812 +10755 +14921 +5929 +14512 +15133 +7920 +6593 +5687 +8889 +15860 +2928 +19630 +6427 +4721 +16681 +11324 +19844 +17817 +10370 +1708 +16101 +347 +10038 +8229 +315 +16837 +17819 +15710 +15957 +1594 +4849 +988 +14540 +14061 +466 +10409 +1590 +13376 +14016 +5551 +2128 +7123 +5960 +2971 +2894 +2673 +113 +18841 +19657 +943 +17769 +10736 +12748 +3823 +10505 +1441 +6012 +5093 +5732 +8689 +4642 +7535 +11738 +12190 +2754 +15430 +390 +6266 +12967 +3068 +18040 +14457 +19114 +17612 +1231 +14044 +17221 +6801 +6131 +763 +9072 +2323 +18702 +11260 +16132 +4616 +3505 +14452 +10756 +191 +8073 +479 +13987 +14278 +10273 +9516 +13779 +11450 +10853 +6560 +10506 +19086 +18039 +9299 +11353 +5320 +16870 +14867 +167 +4794 +17329 +14958 +10076 +17110 +6788 +18190 +16720 +8224 +795 +4646 +6493 +1161 +5263 +10666 +748 +10573 +9966 +6233 +17645 +6417 +16039 +10192 +17280 +6430 +18198 +8044 +4755 +7504 +2203 +6848 +16849 +7324 +7591 +5536 +2021 +18495 +17862 +3744 +11217 +7378 +9632 +10720 +11790 +7906 +8422 +16003 +9140 +11526 +7747 +1148 +17188 +15170 +14893 +2288 +1242 +1044 +15730 +2828 +17845 +15822 +8368 +18914 +3357 +16524 +3520 +7310 +8211 +9024 +6767 +9319 +7926 +7467 +8259 +2377 +2483 +15244 +4914 +17406 +8216 +17683 +19085 +1387 +6646 +14486 +10510 +18046 +11070 +13360 +16754 +15081 +9737 +3911 +4777 +10278 +15289 +14511 +17201 +7858 +18664 +12469 +18097 +6663 +10134 +3399 +3912 +10869 +3442 +17538 +17850 +17631 +2782 +326 +16022 +18134 +9553 +16702 +7882 +7788 +7816 +1877 +1951 +1047 +5321 +11269 +1555 +11555 +10739 +8981 +16342 +13822 +979 +17702 +9247 +921 +18937 +16591 +1535 +13921 +4600 +12206 +12042 +19793 +10602 +19418 +7187 +9416 +4614 +16415 +14096 +13803 +226 +16737 +19230 +13198 +18116 +10277 +14249 +17439 +19986 +13236 +17136 +12900 +5341 +7985 +2679 +5627 +9312 +10199 +16861 +2942 +1852 +10466 +7838 +11922 +8420 +15176 +2986 +17555 +5978 +7507 +4112 +1992 +1988 +6446 +10154 +6176 +16089 +9104 +11211 +18823 +18351 +8555 +11458 +10327 +15240 +3768 +1397 +16753 +1435 +19820 +2920 +17298 +14659 +9014 +16372 +7697 +17405 +11495 +14499 +7238 +2422 +3904 +13281 +17674 +10891 +2231 +16960 +7274 +12581 +14323 +16416 +15765 +724 +17605 +2601 +16006 +4423 +17675 +16772 +15137 +12001 +12449 +14088 +2348 +19239 +19610 +12057 +18615 +11643 +5915 +19006 +9876 +17123 +18082 +17785 +4026 +17663 +17042 +17964 +11624 +5976 +15444 +10059 +15667 +15786 +12511 +11528 +7769 +17282 +12557 +10398 +18996 +2584 +6022 +16775 +14244 +5590 +7363 +875 +6815 +15076 +14959 +557 +2437 +9090 +2020 +19675 +405 +18129 +12453 +18373 +8859 +16864 +17115 +14085 +17182 +11106 +12069 +12909 +7080 +11712 +16142 +217 +7297 +11393 +18678 +14908 +8633 +8695 +10844 +6283 +527 +17049 +8815 +18650 +18884 +13586 +15995 +19789 +4881 +7954 +19487 +12038 +2817 +19863 +9280 +8054 +19464 +13003 +3267 +8071 +16069 +10342 +6306 +11396 +6477 +8864 +5704 +2710 +12199 +19054 +8150 +18916 +598 +1798 +10862 +3564 +2493 +11425 +19355 +43 +2000 +6381 +7100 +11343 +863 +13642 +17638 +268 +13767 +4498 +5229 +3469 +11367 +14847 +4946 +11731 +13604 +11640 +402 +15347 +19050 +10879 +2674 +13005 +15778 +10391 +11884 +3160 +7852 +14628 +18986 +1357 +10049 +15644 +12059 +17044 +10057 +11641 +5467 +19892 +11377 +9988 +4316 +12799 +18538 +1474 +13114 +14950 +5039 +16025 +9250 +10657 +7118 +4222 +19918 +14667 +15052 +16492 +5938 +900 +7900 +7710 +5822 +18875 +8196 +18882 +2880 +1152 +12659 +5037 +10089 +10221 +4065 +13978 +926 +16585 +18992 +12586 +2191 +9141 +528 +19659 +7864 +12705 +19187 +17454 +5459 +794 +2685 +3822 +14642 +12897 +12235 +18761 +7972 +18561 +15638 +3558 +3281 +11239 +12014 +81 +14644 +6095 +7307 +19241 +11026 +19273 +4402 +9027 +17908 +13087 +9145 +5881 +13560 +12142 +15568 +7465 +5444 +16213 +19698 +2972 +6944 +17487 +19328 +2036 +9863 +13626 +18917 +11146 +9070 +19393 +7971 +11890 +5695 +635 +10250 +295 +15996 +17229 +9818 +17134 +15200 +3936 +1634 +12688 +3340 +7352 +18614 +16175 +12743 +12930 +17127 +15322 +11875 +7639 +13703 +17626 +17535 +19031 +6930 +14697 +1825 +16979 +3705 +18768 +8208 +16300 +4000 +11325 +16131 +15139 +12729 +13528 +332 +18635 +16676 +10965 +15507 +7223 +639 +13513 +856 +8973 +9929 +9743 +19521 +19061 +11018 +3185 +11891 +16895 +2198 +19403 +3970 +10820 +9093 +4773 +15782 +10687 +12854 +5884 +11595 +15030 +2711 +5526 +12793 +6369 +6740 +14772 +18938 +3802 +19193 +6108 +4678 +907 +3461 +16201 +5374 +11025 +539 +11369 +2622 +12082 +11433 +9720 +11321 +12455 +2353 +3790 +6902 +449 +7641 +5161 +19164 +14956 +8586 +2591 +16662 +19906 +2380 +12652 +9882 +14462 +779 +8482 +2800 +16037 +15024 +11349 +12814 +9198 +4722 +2446 +1556 +12784 +8673 +16469 +415 +7447 +11195 +10674 +1046 +12767 +18816 +14060 +6056 +4578 +10502 +12510 +2802 +10838 +3637 +1690 +3156 +8481 +1662 +7583 +6152 +1862 +9289 +7438 +7598 +5326 +13903 +16604 +17475 +9371 +3069 +4759 +19035 +16499 +11168 +2194 +10852 +8599 +8552 +4281 +18637 +18012 +375 +15003 +5165 +5574 +16872 +12433 +10637 +5673 +653 +10539 +10521 +8807 +12451 +19728 +10072 +5563 +13953 +8904 +15337 +16685 +19478 +7023 +9759 +616 +15171 +2579 +2117 +10525 +3776 +8050 +12265 +2659 +10955 +4871 +8826 +5215 +8556 +7636 +5354 +9040 +16536 +2478 +4610 +7428 +1310 +14804 +15627 +5729 +13802 +4533 +7916 +17655 +9218 +9878 +8901 +14109 +15473 +18424 +14516 +17854 +922 +9809 +777 +15617 +1328 +6959 +16227 +11101 +16684 +1801 +5166 +3937 +8975 +19858 +5359 +4985 +11760 +5918 +16780 +10560 +15954 +7804 +3155 +6148 +12639 +6777 +120 +15463 +11542 +3639 +1391 +19390 +8181 +7014 +10253 +3250 +15768 +1224 +3635 +17809 +1016 +18230 +8803 +11834 +14932 +9345 +8653 +9225 +17041 +213 +1541 +13991 +16261 +12413 +19838 +8918 +809 +13016 +5260 +5055 +10934 +10983 +19317 +3855 +18375 +13094 +17275 +3345 +582 +8155 +15791 +2259 +9749 +3612 +13735 +1619 +18673 +10429 +7055 +3676 +3787 +11307 +8421 +1385 +5837 +11412 +8363 +9380 +5042 +8496 +10106 +6121 +4167 +18201 +13748 +12307 +109 +6346 +13306 +10480 +12215 +17004 +14747 +13535 +16264 +1172 +14846 +5114 +19359 +11684 +10032 +8835 +12411 +4147 +19345 +2363 +10354 +9495 +9197 +15041 +1943 +19543 +13605 +2240 +7746 +4005 +15943 +2549 +1421 +13992 +15064 +12013 +5570 +18797 +16442 +13196 +6916 +9235 +137 +7200 +5527 +6624 +16927 +13187 +17080 +12312 +5464 +8951 +6445 +9958 +12928 +1917 +14677 +13004 +2429 +4643 +15183 +12254 +19921 +6191 +11831 +13834 +16233 +19879 +4656 +14240 +5820 +13572 +5939 +13868 +4798 +9814 +10744 +4417 +15897 +11917 +12437 +3197 +14604 +646 +17778 +6926 +7007 +18540 +4762 +11729 +6453 +16615 +15672 +8745 +8164 +1053 +10646 +18766 +7477 +14917 +19578 +4236 +6537 +10230 +18156 +10047 +16229 +497 +18798 +9853 +2838 +1259 +8518 +9677 +10997 +18749 +19570 +13151 +13964 +9652 +14081 +2596 +8611 +10570 +10854 +5200 +2944 +951 +12686 +16778 +2324 +17719 +8357 +489 +18662 +18101 +9890 +8036 +1729 +443 +1289 +3196 +12816 +12016 +559 +13561 +5773 +2018 +12529 +19632 +2992 +7877 +8451 +2213 +10654 +1527 +11087 +18384 +9763 +6650 +11809 +1609 +4467 +10204 +1488 +15738 +14701 +15455 +2079 +3456 +11029 +15574 +7377 +9987 +2948 +5175 +14345 +7366 +5213 +7608 +19866 +10247 +3374 +11014 +5775 +8122 +2564 +11404 +10184 +12264 +7048 +18945 +19704 +8325 +18305 +13815 +10132 +6797 +10936 +1702 +10350 +3315 +1039 +19438 +7141 +499 +4415 +17139 +12106 +15573 +13098 +9349 +2740 +6011 +17074 +14704 +13188 +12325 +5268 +128 +3117 +17471 +7712 +19416 +6805 +5840 +18755 +1747 +12198 +2297 +6940 +7928 +3557 +16605 +9100 +3284 +929 +2991 +5171 +9105 +6612 +8201 +17441 +10795 +7211 +9938 +4213 +9610 +15608 +6395 +14637 +18330 +11331 +13876 +9594 +2243 +13102 +12866 +13537 +8418 +15277 +16949 +11213 +19616 +8513 +15023 +14446 +6948 +8498 +10269 +9670 +14458 +6901 +11357 +19957 +10534 +16712 +18348 +1383 +5275 +16251 +333 +2412 +14927 +7276 +1858 +4349 +3275 +648 +5278 +9666 +6384 +7228 +17464 +4764 +16289 +2921 +19010 +7815 +3736 +11913 +19719 +16259 +8890 +18025 +1886 +18121 +4821 +7384 +5276 +11473 +6379 +12858 +13407 +2561 +19861 +7675 +15363 +16265 +10215 +15396 +17059 +14382 +9101 +13831 +17112 +1118 +19648 +12896 +15509 +1621 +18998 +17789 +14808 +2200 +17934 +9253 +16813 +8397 +9695 +17162 +12788 +15149 +4886 +9657 +17540 +5440 +6871 +446 +7966 +3719 +18020 +8594 +19427 +4106 +1655 +11974 +17266 +18550 +5482 +4944 +17868 +8149 +13808 +1459 +677 +4943 +3369 +13600 +12436 +4788 +16414 +13820 +12613 +17079 +9685 +1791 +19696 +11232 +8813 +6279 +13149 +4003 +1331 +4751 +13718 +17326 +10718 +4988 +8720 +13244 +12894 +4469 +19523 +4164 +574 +3262 +3121 +15197 +12488 +14422 +3394 +15618 +12647 +5404 +8148 +18660 +6270 +6769 +12942 +16017 +4344 +14650 +2435 +4241 +18303 +9680 +15286 +13701 +16994 +11131 +7553 +2568 +9968 +6309 +11711 +8818 +14293 +13980 +1157 +6691 +17351 +801 +17557 +1268 +10067 +18697 +15903 +11645 +7544 +7831 +10738 +18610 +19076 +10609 +7455 +12919 +412 +4731 +15175 +9352 +4903 +3856 +12088 +7429 +16924 +5427 +15464 +10176 +11120 +19541 +1626 +17762 +17228 +3076 +17289 +7974 +15069 +17047 +11409 +7799 +2707 +7794 +15153 +16613 +3139 +14179 +12875 +17143 +9761 +12067 +6544 +4249 +6828 +11108 +17891 +13329 +6349 +1526 +14859 +3882 +14876 +13375 +1311 +512 +19351 +1517 +10942 +19710 +12323 +3382 +16148 +9603 +15167 +7444 +1961 +17744 +18475 +6961 +11835 +12011 +13212 +19177 +15521 +16905 +8607 +13854 +905 +4023 +19920 +1113 +665 +888 +16595 +10604 +10613 +6549 +4809 +12713 +6988 +7495 +4539 +1238 +9551 +14471 +13112 +18767 +17729 +10282 +14074 +9360 +12943 +116 +10781 +18042 +8436 +14543 +5234 +5963 +14405 +19971 +1195 +1694 +19717 +16271 +9803 +2931 +3670 +5140 +12918 +9154 +15316 +4203 +5170 +13130 +12889 +18632 +12169 +5109 +4927 +13882 +1892 +9167 +5772 +11017 +7604 +8626 +254 +17357 +519 +11928 +610 +19953 +8246 +1815 +18859 +19000 +11059 +13451 +12572 +7127 +5540 +2675 +12233 +11916 +19785 +5499 +18869 +13170 +14185 +7098 +17890 +7125 +3362 +4796 +12872 +13299 +18437 +1515 +16028 +924 +15969 +13406 +6335 +19083 +19680 +8405 +6974 +14150 +18472 +175 +17704 +6026 +10359 +125 +9949 +323 +16066 +8426 +9705 +17840 +11618 +16405 +17831 +5495 +7925 +5446 +13136 +16856 +501 +5798 +5046 +18804 +2436 +15071 +1789 +3595 +9365 +573 +14080 +6014 +1401 +10190 +7089 +1300 +15946 +5040 +3788 +7285 +10547 +8250 +13270 +19474 +5254 +18304 +3166 +8157 +14246 +1905 +18877 +1826 +14292 +2116 +14290 +14303 +19315 +3500 +1440 +17336 +4125 +5832 +13656 +7446 +1578 +18255 +13466 +2394 +10357 +10322 +16599 +484 +14238 +16871 +576 +19975 +13303 +3587 +11715 +3858 +19108 +13193 +6484 +16913 +13746 +3689 +7785 +11274 +3226 +867 +3521 +9875 +7548 +11683 +2938 +2808 +10639 +5637 +12182 +14113 +8393 +19388 +14595 +2186 +13448 +16746 +4338 +14350 +6545 +15318 +11072 +12553 +189 +5154 +19178 +14990 +7640 +16551 +114 +1718 +17988 +16207 +18663 +8784 +19889 +15104 +14822 +10831 +1235 +3859 +6637 +8056 +15442 +3255 +12219 +1651 +13557 +2588 +674 +4427 +1533 +790 +4406 +19996 +6344 +6631 +2247 +5894 +5984 +9042 +18361 +16707 +1207 +10035 +2604 +9086 +9038 +2093 +9184 +12278 +14256 +475 +18083 +376 +16078 +17109 +16982 +6483 +14280 +18418 +18093 +16337 +12183 +11093 +11437 +16118 +14962 +13543 +11745 +4113 +5099 +13806 +19115 +15015 +16645 +10805 +16214 +19047 +12324 +16211 +18511 +16564 +14116 +7889 +1392 +16836 +764 +5843 +6642 +10019 +652 +9520 +12063 +12796 +5614 +3854 +13715 +1967 +6234 +19116 +17506 +5372 +1757 +9779 +1602 +17388 +1426 +10242 +15945 +15458 +16226 +3591 +1600 +8249 +19284 +11497 +19087 +19865 +1171 +13498 +9789 +11682 +10949 +1897 +16649 +6389 +17446 +4783 +6917 +7019 +16224 +11046 +6236 +15851 +1965 +6323 +15120 +13774 +1913 +668 +6193 +11617 +18867 +1839 +1507 +19433 +18326 +5922 +15468 +14764 +19434 +15915 +17531 +2201 +9970 +8108 +6647 +3871 +15044 +198 +13071 +13836 +2234 +3248 +7027 +18630 +6894 +8504 +14268 +13542 +12579 +4510 +14641 +11348 +10437 +411 +9682 +13850 +12554 +2215 +4432 +19754 +6577 +6692 +5885 +13896 +13530 +8995 +8984 +6713 +1638 +13610 +12847 +8177 +17639 +5061 +7959 +16560 +5002 +5882 +10017 +7224 +2383 +395 +10415 +14874 +10808 +19361 +1853 +5595 +2833 +2630 +4200 +9069 +953 +1704 +2651 +5490 +15447 +6469 +18785 +15647 +8618 +18836 +8001 +6054 +12794 +8130 +11472 +14941 +12022 +5015 +14748 +19796 +10336 +16788 +9751 +8247 +16711 +5665 +480 +9231 +19950 +9124 +5067 +12568 +8320 +16221 +12513 +4007 +11214 +7084 +18858 +15861 +5809 +3408 +12988 +18103 +2228 +2414 +11002 +11463 +487 +2084 +873 +1499 +6827 +8902 +19125 +1699 +6154 +29 +14125 +9699 +16418 +3683 +6248 +7809 +2144 +9001 +8404 +8930 +6509 +10207 +2609 +14163 +15598 +5857 +731 +6295 +16312 +13307 +8062 +18874 +6720 +14190 +9457 +18814 +18570 +4360 +18309 +6782 +9548 +14992 +17017 +16082 +2331 +6703 +13941 +16808 +6596 +18048 +12268 +2472 +11044 +19068 +18961 +3910 +14000 +9847 +2769 +4774 +15335 +2071 +7173 +13524 +16700 +1006 +4290 +9556 diff --git a/tests/fixtures/test/non_empty_file b/tests/fixtures/test/non_empty_file new file mode 100644 index 000000000..34425caf6 --- /dev/null +++ b/tests/fixtures/test/non_empty_file @@ -0,0 +1 @@ +Not empty! diff --git a/tests/fixtures/test/regular_file b/tests/fixtures/test/regular_file new file mode 100644 index 000000000..e69de29bb diff --git a/tests/fixtures/wc/emptyfile.txt b/tests/fixtures/wc/emptyfile.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/fixtures/wc/manyemptylines.txt b/tests/fixtures/wc/manyemptylines.txt new file mode 100644 index 000000000..716f02896 --- /dev/null +++ b/tests/fixtures/wc/manyemptylines.txt @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/fixtures/wc/notrailingnewline.txt b/tests/fixtures/wc/notrailingnewline.txt new file mode 100644 index 000000000..789819226 --- /dev/null +++ b/tests/fixtures/wc/notrailingnewline.txt @@ -0,0 +1 @@ +a diff --git a/tests/fixtures/wc/onelongemptyline.txt b/tests/fixtures/wc/onelongemptyline.txt new file mode 100644 index 000000000..f93ac3c2c --- /dev/null +++ b/tests/fixtures/wc/onelongemptyline.txt @@ -0,0 +1 @@ + diff --git a/tests/fixtures/wc/onelongword.txt b/tests/fixtures/wc/onelongword.txt new file mode 100644 index 000000000..9d693a7ca --- /dev/null +++ b/tests/fixtures/wc/onelongword.txt @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa