summaryrefslogtreecommitdiff
path: root/Phone Book
diff options
context:
space:
mode:
Diffstat (limited to 'Phone Book')
-rw-r--r--Phone Book/A needle in the hay/task-info.yaml68
-rw-r--r--Phone Book/A needle in the hay/task-remote-info.yaml2
-rw-r--r--Phone Book/A needle in the hay/task.html26
-rw-r--r--Phone Book/Instant search/task-info.yaml85
-rw-r--r--Phone Book/Instant search/task-remote-info.yaml2
-rw-r--r--Phone Book/Instant search/task.html29
-rw-r--r--Phone Book/Jumping bubbles/task-info.yaml75
-rw-r--r--Phone Book/Jumping bubbles/task-remote-info.yaml2
-rw-r--r--Phone Book/Jumping bubbles/task.html33
-rw-r--r--Phone Book/Need for speed/task-info.yaml77
-rw-r--r--Phone Book/Need for speed/task-remote-info.yaml2
-rw-r--r--Phone Book/Need for speed/task.html24
-rw-r--r--Phone Book/lesson-info.yaml7
-rw-r--r--Phone Book/task/build/classes/java/main/phonebook/Main.classbin0 -> 2493 bytes
-rw-r--r--Phone Book/task/build/classes/java/test/PhoneBookTest.classbin0 -> 4760 bytes
-rw-r--r--Phone Book/task/build/reports/tests/test/classes/PhoneBookTest.html113
-rw-r--r--Phone Book/task/build/reports/tests/test/css/base-style.css179
-rw-r--r--Phone Book/task/build/reports/tests/test/css/style.css84
-rw-r--r--Phone Book/task/build/reports/tests/test/index.html133
-rw-r--r--Phone Book/task/build/reports/tests/test/js/report.js194
-rw-r--r--Phone Book/task/build/reports/tests/test/packages/default-package.html103
-rw-r--r--Phone Book/task/build/test-results/test/TEST-PhoneBookTest.xml15
-rw-r--r--Phone Book/task/build/test-results/test/binary/output.bin8
-rw-r--r--Phone Book/task/build/test-results/test/binary/output.bin.idxbin0 -> 36 bytes
-rw-r--r--Phone Book/task/build/test-results/test/binary/results.binbin0 -> 65 bytes
-rw-r--r--Phone Book/task/build/tmp/compileJava/previous-compilation-data.binbin0 -> 102 bytes
-rw-r--r--Phone Book/task/build/tmp/compileTestJava/previous-compilation-data.binbin0 -> 725 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_10538721871324043965_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_1077730010440405004_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_10902530340676372483_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_10960595819529319986_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_11876933921394287305_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_12948572776275551361_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_14295399020760462387_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_14295563507054793625_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_14784488148707108206_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_1485319623633347147_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_14994615155820603177_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_17625680219941505665_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_250031160504055896_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_3476398348885347998_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_5327178042574920376_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_5448310131170567508_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_5675441501024301266_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_7220357135091350547_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_765866268204397014_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_8427334914632652757_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_908946969250790051_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_9316444809127863590_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/build/tmp/test/jar_extract_9728816399475840109_tmpbin0 -> 9644 bytes
-rw-r--r--Phone Book/task/out/production/classes/phonebook/Main.classbin0 -> 2531 bytes
-rw-r--r--Phone Book/task/src/phonebook/Main.java42
-rw-r--r--Phone Book/task/test/PhoneBookTest.java93
53 files changed, 1396 insertions, 0 deletions
diff --git a/Phone Book/A needle in the hay/task-info.yaml b/Phone Book/A needle in the hay/task-info.yaml
new file mode 100644
index 0000000..ae3121b
--- /dev/null
+++ b/Phone Book/A needle in the hay/task-info.yaml
@@ -0,0 +1,68 @@
+type: edu
+custom_name: stage1
+files:
+- name: src/phonebook/Main.java
+ visible: true
+ text: |
+ package phonebook;
+
+ public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ }
+ }
+ learner_created: false
+- name: test/PhoneBookTest.java
+ visible: false
+ text: "import org.hyperskill.hstest.stage.StageTest;\nimport org.hyperskill.hstest.testcase.CheckResult;\n\
+ import org.hyperskill.hstest.testcase.TestCase;\n\nimport java.util.Arrays;\n\
+ import java.util.List;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\
+ \npublic class PhoneBookTest extends StageTest {\n\n private long timeOnTestStart;\n\
+ \ private static String outputFirstTest;\n \n @Override\n public List<TestCase>\
+ \ generate() {\n timeOnTestStart = System.currentTimeMillis();\n \
+ \ return Arrays.asList(\n new TestCase<>().setTimeLimit(30 * 60\
+ \ * 1000),\n new TestCase<>().setTimeLimit(30 * 60 * 1000).setCheckFunc((reply,\
+ \ attach) -> {\n if (reply.equals(outputFirstTest)) {\n \
+ \ return CheckResult.wrong(\n \"\
+ Your program output is exactly the same during different runs. \" +\n \
+ \ \"Does your program just output a string?\"\n \
+ \ );\n\n }\n return CheckResult.correct();\n\
+ \ })\n );\n }\n \n private CheckResult checkPhrases(String\
+ \ reply, String... phrases) {\n reply = reply.toLowerCase();\n for\
+ \ (String phrase : phrases) {\n if (!reply.contains(phrase.toLowerCase()))\
+ \ {\n return CheckResult.wrong(\"Not found the part `\" + phrase\
+ \ + \"` in your output.\");\n }\n }\n return CheckResult.correct();\n\
+ \ }\n \n private Pattern timePattern = Pattern.compile(\".*(\\\\d+)\\\
+ \\s*min.*?(\\\\d+)\\\\s*sec.*?(\\\\d+)\\\\s*ms.*\", Pattern.DOTALL);\n \n \
+ \ // returns -1 if not matches.\n private long getUserEstimatedTime(String\
+ \ reply) {\n Matcher matcher = timePattern.matcher(reply);\n if\
+ \ (!matcher.matches()) {\n return -1;\n }\n int min =\
+ \ Integer.parseInt(matcher.group(1));\n int sec = Integer.parseInt(matcher.group(2));\n\
+ \ int ms = Integer.parseInt(matcher.group(3));\n \n return\
+ \ ms + sec * 1000 + min * 1000 * 60;\n }\n \n @Override\n public CheckResult\
+ \ check(String reply, Object clue) {\n\n outputFirstTest = reply;\n\n \
+ \ long realTime = System.currentTimeMillis() - timeOnTestStart;\n \
+ \ timeOnTestStart = System.currentTimeMillis();\n// System.out.println(\"\
+ Time delta: \" + realTime);\n \n if (!reply.contains(\"500 / 500\"\
+ ) && !reply.contains(\"500/500\")) {\n return CheckResult.wrong(\"\
+ Your output should contain `500 / 500` fragment.\");\n }\n \n \
+ \ CheckResult res = checkPhrases(reply, \"start searching\", \"found\",\n\
+ \ \"min.\", \"sec.\", \"ms.\");\n if (!res.isCorrect())\
+ \ {\n return res;\n }\n long estimatedTime = getUserEstimatedTime(reply);\n\
+ \ if (estimatedTime == -1) {\n return CheckResult.wrong(\"Your\
+ \ output format doesn't contain numbers before min, sec, ms words.\");\n \
+ \ }\n \n if (realTime < 1000) {\n return CheckResult.wrong(\"\
+ Your program completes too fast. Faster than a second!\");\n }\n \
+ \ \n double ratio = estimatedTime / (realTime + 0.0);\n if (ratio\
+ \ < 0.5 || ratio > 1.5) {\n return CheckResult.wrong(\"Too large difference\
+ \ between the real working time and your output. \" +\n \"\
+ Real program working time was \" + realTime + \" ms, and your output contained\
+ \ \" + estimatedTime + \"ms in total.\");\n }\n \n return\
+ \ CheckResult.correct();\n }\n}\n"
+ learner_created: false
+feedback_link: https://hyperskill.org/projects/63/stages/340/implement#comment
+status: Solved
+feedback:
+ message: Congratulations!
+ time: Wed, 27 Apr 2022 15:20:47 UTC
+record: -1
diff --git a/Phone Book/A needle in the hay/task-remote-info.yaml b/Phone Book/A needle in the hay/task-remote-info.yaml
new file mode 100644
index 0000000..93b8bed
--- /dev/null
+++ b/Phone Book/A needle in the hay/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 5482
+update_date: Fri, 11 Mar 2022 08:50:15 UTC
diff --git a/Phone Book/A needle in the hay/task.html b/Phone Book/A needle in the hay/task.html
new file mode 100644
index 0000000..dcfb2dd
--- /dev/null
+++ b/Phone Book/A needle in the hay/task.html
@@ -0,0 +1,26 @@
+<h5 style="text-align: center;" id="description">Description</h5>
+
+<p>Have you ever had to use one of those 2000+ page phone books full of various organizations and people's names, written in a small font and with multiple columns on each page? Finding the information you need in such books can be an ordeal. In fact, even computers struggle to search through the millions of entries in a directory.</p>
+
+<p>In this project, you will create a phone book, implementing several algorithms, and comparing their efficiency when using a big dataset.</p>
+
+<p>For this, you will need to download the file <a target="_blank" target="_blank" href="https://stepik.org/media/attachments/lesson/197761/directory.txt" rel="nofollow noopener noreferrer">directory.txt</a> that contains the phone numbers of over a million people in multiple cities.</p>
+
+<p>At this stage, you should implement the simplest possible search to find the numbers of a few people whose names are listed in the file <a target="_blank" target="_blank" href="https://stepik.org/media/attachments/lesson/197761/find.txt" rel="nofollow noopener noreferrer">find.txt</a>.</p>
+
+<p>It takes a time to find all the records from the big file. We recommend you manually test your program with the simplified data: <a target="_blank" target="_blank" href="https://stepik.org/media/attachments/lesson/210117/small_directory.txt" rel="noopener noreferrer nofollow">small_directory.txt</a> and <a target="_blank" target="_blank" href="https://stepik.org/media/attachments/lesson/210117/small_find.txt" rel="noopener noreferrer nofollow">small_find.txt</a>. But to pass all the tests you have to work with the big files above.</p>
+
+<p>Note how long it takes you to do this when using a linear search so that you can compare results with other search methods.</p>
+
+<p>To measure the time difference, you can use <code class="java">System.currentTimeMillis()</code>.</p>
+
+<p>Also notice that you don't need to read the file "directory.txt" again and again after each query. You should load all lines into memory and measure only the search process.</p>
+
+<p><div class="alert alert-warning">Please, do not keep the downloaded files inside your project directory because the server can reject large files and you will see the message <strong>"Failed to post submission to the Hyperskill"</strong>.</div></p>
+
+<h5 style="text-align: center;" id="example">Example</h5>
+
+<p>Below is an example of how your output should look:</p>
+
+<pre><code class="java">Start searching...
+Found 500 / 500 entries. Time taken: 1 min. 56 sec. 328 ms.</code></pre> \ No newline at end of file
diff --git a/Phone Book/Instant search/task-info.yaml b/Phone Book/Instant search/task-info.yaml
new file mode 100644
index 0000000..6fd9cf2
--- /dev/null
+++ b/Phone Book/Instant search/task-info.yaml
@@ -0,0 +1,85 @@
+type: edu
+custom_name: stage4
+files:
+- name: src/phonebook/Main.java
+ visible: true
+ text: |
+ package phonebook;
+
+ public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ }
+ }
+ learner_created: false
+- name: test/PhoneBookTest.java
+ visible: false
+ text: "import org.hyperskill.hstest.stage.StageTest;\nimport org.hyperskill.hstest.testcase.CheckResult;\n\
+ import org.hyperskill.hstest.testcase.TestCase;\n\nimport java.util.ArrayList;\n\
+ import java.util.Arrays;\nimport java.util.List;\nimport java.util.regex.Matcher;\n\
+ import java.util.regex.Pattern;\n\npublic class PhoneBookTest extends StageTest\
+ \ {\n\n private long timeOnTestStart;\n \n @Override\n public List<TestCase>\
+ \ generate() {\n timeOnTestStart = System.currentTimeMillis();\n \
+ \ return Arrays.asList(\n new TestCase().setTimeLimit(30 * 60 * 1000)\n\
+ \ );\n }\n \n \n private CheckResult checkPhrases(String reply,\
+ \ String... phrases) {\n reply = reply.toLowerCase();\n for (String\
+ \ phrase : phrases) {\n if (!reply.contains(phrase.toLowerCase()))\
+ \ {\n return CheckResult.wrong(\"Not found the part `\" + phrase\
+ \ + \"` in your output.\");\n }\n }\n return CheckResult.correct();\n\
+ \ }\n \n private List<String> findAll(String reply, String regex) {\n\
+ \ Matcher matcher = Pattern.compile(regex).matcher(reply);\n List<String>\
+ \ groups = new ArrayList<>();\n while (matcher.find()) {\n groups.add(matcher.group());\n\
+ \ }\n return groups;\n }\n \n private String timeRegex\
+ \ = \"(\\\\d+)\\\\s*min.*?(\\\\d+)\\\\s*sec.*?(\\\\d+)\\\\s*ms\";\n private\
+ \ Pattern timeRegexPattern = Pattern.compile(timeRegex);\n \n private long\
+ \ parseTimestamp(String timestamp) {\n Matcher matcher = timeRegexPattern.matcher(timestamp);\n\
+ \ if (!matcher.matches() || matcher.groupCount() < 3) {\n throw\
+ \ new IllegalStateException(\"???Not matches the line \" + timestamp);\n \
+ \ }\n int min = Integer.parseInt(matcher.group(1));\n int sec\
+ \ = Integer.parseInt(matcher.group(2));\n int ms = Integer.parseInt(matcher.group(3));\n\
+ \ return ms + sec * 1000 + min * 1000 * 60;\n }\n \n \n \n\
+ \ @Override\n public CheckResult check(String reply, Object clue) {\n \
+ \ long realTime = System.currentTimeMillis() - timeOnTestStart;\n \
+ \ reply = reply.toLowerCase();\n CheckResult res = checkPhrases(reply,\n\
+ \ \"found\",\n \"min.\",\n \"sec.\"\
+ ,\n \"ms.\",\n \"sorting time\",\n \
+ \ \"searching time\",\n \"linear search\",\n \"\
+ bubble sort\",\n \"jump search\",\n \"quick sort\"\
+ ,\n \"binary search\",\n \"hash table\",\n \
+ \ \"creating time\"\n );\n if (!res.isCorrect()) {\n \
+ \ return res;\n }\n \n List<String> stat1 = findAll(reply,\
+ \ \"500 / 500\");\n List<String> stat2 = findAll(reply, \"500/500\");\n\
+ \ \n if (stat1.size() + stat2.size() < 4) {\n return CheckResult.wrong(\"\
+ Your output should contain 4 times the phrase `500 / 500`\");\n }\n \
+ \ \n List<String> timestamps = findAll(reply, timeRegex);\n if (timestamps.size()\
+ \ != 10) {\n return CheckResult.wrong(\"Your output should contain\
+ \ 10 timer outputs, but found \"\n + timestamps.size());\n\
+ \ }\n // should not fail..\n long t1 = parseTimestamp(timestamps.get(0));\n\
+ \ long t2 = parseTimestamp(timestamps.get(1));\n long t3 = parseTimestamp(timestamps.get(2));\n\
+ \ long t4 = parseTimestamp(timestamps.get(3));\n // qsort\n \
+ \ long t5 = parseTimestamp(timestamps.get(4));\n long t6 = parseTimestamp(timestamps.get(5));\n\
+ \ long t7 = parseTimestamp(timestamps.get(6));\n // hash table\n\
+ \ long t8 = parseTimestamp(timestamps.get(7));\n long t9 = parseTimestamp(timestamps.get(8));\n\
+ \ long t10 = parseTimestamp(timestamps.get(9));\n \n if (Math.abs(t3\
+ \ + t4 - t2) > 100) {\n return CheckResult.wrong(\"Your third and fourth\
+ \ timer outputs in total (bubble sorting and searching) \" +\n \
+ \ \"should be equal to the second (total search time).\");\n }\n \
+ \ if (Math.abs(t6 + t7 - t5) > 100) {\n return CheckResult.wrong(\"\
+ Your 6-th and 7-th timer outputs in total (qsort and searching) \" +\n \
+ \ \"should be equal to the 5-th (total search time).\");\n \
+ \ }\n if (Math.abs(t9 + t10 - t8) > 100) {\n return CheckResult.wrong(\"\
+ Your 9-th and 10-th timer outputs in total (creating hashtable and searching)\
+ \ \" +\n \"should be equal to the 8-th (total search time).\"\
+ );\n }\n \n long estimatedTime = t1 + t2 + t5 + t8;\n \
+ \ if (realTime < 1000) {\n return CheckResult.wrong(\"Your program\
+ \ completes too fast. Faster than a second!\");\n }\n\n if (Math.abs(estimatedTime\
+ \ - realTime) > estimatedTime * 0.3) {\n return CheckResult.wrong(\"\
+ Your estimated time is not similar to real time the program works. \" +\n \
+ \ \"Real time: \" + realTime + \"ms, estimated time: \" + estimatedTime\
+ \ + \"ms\");\n }\n \n if (t8 >= t5) {\n return\
+ \ CheckResult.wrong(\"Your hashtable works slower, than quick sort + binary search.\"\
+ );\n }\n return CheckResult.correct();\n }\n}\n"
+ learner_created: false
+feedback_link: https://hyperskill.org/projects/63/stages/475/implement#comment
+status: Unchecked
+record: -1
diff --git a/Phone Book/Instant search/task-remote-info.yaml b/Phone Book/Instant search/task-remote-info.yaml
new file mode 100644
index 0000000..188c90c
--- /dev/null
+++ b/Phone Book/Instant search/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 7721
+update_date: Tue, 28 Dec 2021 18:04:22 UTC
diff --git a/Phone Book/Instant search/task.html b/Phone Book/Instant search/task.html
new file mode 100644
index 0000000..77782f1
--- /dev/null
+++ b/Phone Book/Instant search/task.html
@@ -0,0 +1,29 @@
+<h5 style="text-align: center;" id="description">Description</h5>
+
+<p>The search is pretty fast, but is it possible to come up with something even faster?</p>
+
+<p>In the previous stage, you prepared the data using an algorithm with a complexity of <code class="java">O(n log n)</code> and found the data using an algorithm with a complexity of <code class="java">O(log n)</code>. At this stage, you will implement faster data preparation and a faster search. The preparation will have a complexity of <code class="java">O(n)</code>, and the search will have a complexity of <code class="java">O(1)</code>. A <strong>hash table</strong> will help you with this.</p>
+
+<p>You need to add all the elements to the hash table and then find the necessary phone numbers, as in the previous stages. Since the hash table is filled once, you need to measure the hash table creation time separately (just like you did with sorting in the previous stage).</p>
+
+<h5 style="text-align: center;" id="example">Example</h5>
+
+<p>Output all four approaches one after another and see which one is faster. The output example is shown below. Note that you can get totally different sorting and searching times!</p>
+
+<pre><code class="java">Start searching (linear search)...
+Found 500 / 500 entries. Time taken: 1 min. 56 sec. 328 ms.
+
+Start searching (bubble sort + jump search)...
+Found 500 / 500 entries. Time taken: 9 min. 15 sec. 291 ms.
+Sorting time: 8 min. 45 sec. 251 ms.
+Searching time: 0 min. 30 sec. 40 ms.
+
+Start searching (quick sort + binary search)...
+Found 500 / 500 entries. Time taken: 1 min. 21 sec. 996 ms.
+Sorting time: 1 min. 17 sec. 381 ms.
+Searching time: 0 min. 4 sec. 615 ms.
+
+Start searching (hash table)...
+Found 500 / 500 entries. Time taken: 0 min. 4 sec. 256 ms.
+Creating time: 0 min. 4 sec. 121 ms.
+Searching time: 0 min. 0 sec. 135 ms.</code></pre> \ No newline at end of file
diff --git a/Phone Book/Jumping bubbles/task-info.yaml b/Phone Book/Jumping bubbles/task-info.yaml
new file mode 100644
index 0000000..383ec27
--- /dev/null
+++ b/Phone Book/Jumping bubbles/task-info.yaml
@@ -0,0 +1,75 @@
+type: edu
+custom_name: stage2
+files:
+- name: src/phonebook/Main.java
+ visible: true
+ text: |
+ package phonebook;
+
+ public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ }
+ }
+ learner_created: false
+- name: test/PhoneBookTest.java
+ visible: false
+ text: "import org.hyperskill.hstest.stage.StageTest;\nimport org.hyperskill.hstest.testcase.CheckResult;\n\
+ import org.hyperskill.hstest.testcase.TestCase;\n\nimport java.util.ArrayList;\n\
+ import java.util.Arrays;\nimport java.util.List;\nimport java.util.regex.Matcher;\n\
+ import java.util.regex.Pattern;\n\npublic class PhoneBookTest extends StageTest\
+ \ {\n\n private long timeOnTestStart;\n \n @Override\n public List<TestCase>\
+ \ generate() {\n timeOnTestStart = System.currentTimeMillis();\n \
+ \ return Arrays.asList(\n new TestCase().setTimeLimit(30 * 60\
+ \ * 1000)\n );\n }\n \n private CheckResult checkPhrases(String\
+ \ reply, String... phrases) {\n reply = reply.toLowerCase();\n for\
+ \ (String phrase : phrases) {\n if (!reply.contains(phrase.toLowerCase()))\
+ \ {\n return CheckResult.wrong(\"Not found the part `\" + phrase\
+ \ + \"` in your output.\");\n }\n }\n return CheckResult.correct();\n\
+ \ }\n \n private List<String> findAll(String reply, String regex) {\n\
+ \ Matcher matcher = Pattern.compile(regex).matcher(reply);\n List<String>\
+ \ groups = new ArrayList<>();\n while (matcher.find()) {\n groups.add(matcher.group());\n\
+ \ }\n return groups;\n }\n \n private String timeRegex\
+ \ = \"(\\\\d+)\\\\s*min.*?(\\\\d+)\\\\s*sec.*?(\\\\d+)\\\\s*ms\";\n private\
+ \ Pattern timeRegexPattern = Pattern.compile(timeRegex);\n \n private long\
+ \ parseTimestamp(String timestamp) {\n Matcher matcher = timeRegexPattern.matcher(timestamp);\n\
+ \ if (!matcher.matches() || matcher.groupCount() < 3) {\n throw\
+ \ new IllegalStateException(\"???Not matches the line \" + timestamp);\n \
+ \ }\n int min = Integer.parseInt(matcher.group(1));\n int sec\
+ \ = Integer.parseInt(matcher.group(2));\n int ms = Integer.parseInt(matcher.group(3));\n\
+ \ return ms + sec * 1000 + min * 1000 * 60;\n }\n \n @Override\n\
+ \ public CheckResult check(String reply, Object clue) {\n long realTime\
+ \ = System.currentTimeMillis() - timeOnTestStart;\n \n reply = reply.toLowerCase();\n\
+ \ \n CheckResult res = checkPhrases(reply,\n \"found\"\
+ ,\n \"min.\",\n \"sec.\",\n \"ms.\"\
+ ,\n \"sorting time\",\n \"searching time\",\n \
+ \ \"linear search\",\n \"bubble sort\",\n \
+ \ \"jump search\");\n if (!res.isCorrect()) {\n return\
+ \ res;\n }\n \n List<String> stat1 = findAll(reply, \"500\
+ \ / 500\");\n List<String> stat2 = findAll(reply, \"500/500\");\n \
+ \ \n if (stat1.size() + stat2.size() < 2) {\n return CheckResult.wrong(\"\
+ Your output should contain twice the phrase `500 / 500`\");\n }\n \
+ \ \n \n List<String> timestamps = findAll(reply, timeRegex);\n\
+ \ if (timestamps.size() != 4) {\n return CheckResult.wrong(\"\
+ Your output should contain 4 timer outputs, but found \"\n \
+ \ + timestamps.size());\n }\n // should not fail..\n long\
+ \ t1 = parseTimestamp(timestamps.get(0));\n long t2 = parseTimestamp(timestamps.get(1));\n\
+ \ long t3 = parseTimestamp(timestamps.get(2));\n long t4 = parseTimestamp(timestamps.get(3));\n\
+ \ \n if (Math.abs(t3 + t4 - t2) > 100) {\n return CheckResult.wrong(\"\
+ Your third and fourth timer outputs in total (sorting and searching) \" +\n \
+ \ \"should be equal to the second (total search time).\");\n\
+ \ }\n \n long estimatedTime = t1 + t2;\n if (realTime\
+ \ < 1000) {\n return CheckResult.wrong(\"Your program completes too\
+ \ fast. Faster than a second!\");\n }\n \n if (Math.abs(estimatedTime\
+ \ - realTime) > estimatedTime * 0.3) {\n return CheckResult.wrong(\"\
+ Your estimated time is not similar to real time the program works. \" +\n \
+ \ \"Real time: \" + realTime + \"ms, estimated time: \" + estimatedTime\
+ \ + \"ms\");\n }\n \n if (reply.toLowerCase().contains(\"\
+ stopped\")) {\n if (t3 < t1) {\n return CheckResult.wrong(\"\
+ You printed `stopped`, \" +\n \"but the sorting time was\
+ \ less than the first linear search time.\");\n }\n }\n \
+ \ \n return CheckResult.correct();\n }\n}\n"
+ learner_created: false
+feedback_link: https://hyperskill.org/projects/63/stages/341/implement#comment
+status: Unchecked
+record: -1
diff --git a/Phone Book/Jumping bubbles/task-remote-info.yaml b/Phone Book/Jumping bubbles/task-remote-info.yaml
new file mode 100644
index 0000000..6bde784
--- /dev/null
+++ b/Phone Book/Jumping bubbles/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 5483
+update_date: Tue, 28 Dec 2021 18:04:20 UTC
diff --git a/Phone Book/Jumping bubbles/task.html b/Phone Book/Jumping bubbles/task.html
new file mode 100644
index 0000000..9e3b970
--- /dev/null
+++ b/Phone Book/Jumping bubbles/task.html
@@ -0,0 +1,33 @@
+<h5 style="text-align: center;" id="description">Description</h5>
+
+<p>You have to iterate over each element of the number list every time you want to find someone's number. This is the only way to search if your list contains unordered data. Any number can be anywhere on the list, so you have to check every element.</p>
+
+<p>At this stage, you should sort the list of numbers alphabetically by the owner’s name. Sort the list using the <strong>bubble sort</strong> algorithm and search in the list using the <strong>jump search</strong> algorithm.</p>
+
+<p>After sorting, search for 500 phone numbers using the list from the previous stage. Note how long it takes to sort the list, and also measure the time the program spends searching. Don't include the sorting time in the searching time, because the list of numbers stays sorted after every search request. If you want to save the sorted list into the file so you don’t have to sort it again, do not override the file that contains the unsorted list of phone numbers. This file will also be required in the next stage.</p>
+
+<p>If the sorting process takes too long (more than 10 times longer than all 500 iterations of the linear search), you should stop sorting and use the linear search. Look at the second example to see what you need to output.</p>
+
+<h5 style="text-align: center;" id="example">Example</h5>
+
+<p>Output both approaches one after another and see which one is faster. The output example is shown below. Note that you can get totally different sorting and searching times!</p>
+
+<p><strong>Example 1:</strong></p>
+
+<pre><code class="java">Start searching (linear search)...
+Found 500 / 500 entries. Time taken: 1 min. 56 sec. 328 ms.
+
+Start searching (bubble sort + jump search)...
+Found 500 / 500 entries. Time taken: 9 min. 15 sec. 291 ms.
+Sorting time: 8 min. 45 sec. 251 ms.
+Searching time: 0 min. 30 sec. 40 ms.</code></pre>
+
+<p><strong>Example 2: </strong></p>
+
+<pre><code class="java">Start searching (linear search)...
+Found 500 / 500 entries. Time taken: 2 min. 01 sec. 134 ms.
+
+Start searching (bubble sort + jump search)...
+Found 500 / 500 entries. Time taken: 22 min. 14 sec. 482 ms.
+Sorting time: 20 min. 12 sec. 251 ms. - STOPPED, moved to linear search
+Searching time: 2 min. 02 sec. 231 ms.</code></pre> \ No newline at end of file
diff --git a/Phone Book/Need for speed/task-info.yaml b/Phone Book/Need for speed/task-info.yaml
new file mode 100644
index 0000000..7864f71
--- /dev/null
+++ b/Phone Book/Need for speed/task-info.yaml
@@ -0,0 +1,77 @@
+type: edu
+custom_name: stage3
+files:
+- name: src/phonebook/Main.java
+ visible: true
+ text: |
+ package phonebook;
+
+ public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ }
+ }
+ learner_created: false
+- name: test/PhoneBookTest.java
+ visible: false
+ text: "import org.hyperskill.hstest.stage.StageTest;\nimport org.hyperskill.hstest.testcase.CheckResult;\n\
+ import org.hyperskill.hstest.testcase.TestCase;\n\nimport java.util.ArrayList;\n\
+ import java.util.Arrays;\nimport java.util.List;\nimport java.util.regex.Matcher;\n\
+ import java.util.regex.Pattern;\n\npublic class PhoneBookTest extends StageTest\
+ \ {\n\n private long timeOnTestStart;\n \n @Override\n public List<TestCase>\
+ \ generate() {\n timeOnTestStart = System.currentTimeMillis();\n \
+ \ return Arrays.asList(\n new TestCase().setTimeLimit(30 * 60\
+ \ * 1000)\n );\n }\n \n private CheckResult checkPhrases(String\
+ \ reply, String... phrases) {\n reply = reply.toLowerCase();\n for\
+ \ (String phrase : phrases) {\n if (!reply.contains(phrase.toLowerCase()))\
+ \ {\n return CheckResult.wrong(\"Not found the part `\" + phrase\
+ \ + \"` in your output.\");\n }\n }\n return CheckResult.correct();\n\
+ \ }\n \n private List<String> findAll(String reply, String regex) {\n\
+ \ Matcher matcher = Pattern.compile(regex).matcher(reply);\n List<String>\
+ \ groups = new ArrayList<>();\n while (matcher.find()) {\n groups.add(matcher.group());\n\
+ \ }\n return groups;\n }\n \n private String timeRegex\
+ \ = \"(\\\\d+)\\\\s*min.*?(\\\\d+)\\\\s*sec.*?(\\\\d+)\\\\s*ms\";\n private\
+ \ Pattern timeRegexPattern = Pattern.compile(timeRegex);\n \n private long\
+ \ parseTimestamp(String timestamp) {\n Matcher matcher = timeRegexPattern.matcher(timestamp);\n\
+ \ if (!matcher.matches() || matcher.groupCount() < 3) {\n throw\
+ \ new IllegalStateException(\"???Not matches the line \" + timestamp);\n \
+ \ }\n int min = Integer.parseInt(matcher.group(1));\n int sec\
+ \ = Integer.parseInt(matcher.group(2));\n int ms = Integer.parseInt(matcher.group(3));\n\
+ \ return ms + sec * 1000 + min * 1000 * 60;\n }\n \n @Override\n\
+ \ public CheckResult check(String reply, Object clue) {\n long realTime\
+ \ = System.currentTimeMillis() - timeOnTestStart;\n \n reply = reply.toLowerCase();\n\
+ \ \n CheckResult res = checkPhrases(reply,\n \"found\"\
+ ,\n \"min.\",\n \"sec.\",\n \"ms.\"\
+ ,\n \"sorting time\",\n \"searching time\",\n \
+ \ \"linear search\",\n \"bubble sort\",\n \
+ \ \"jump search\",\n \"quick sort\",\n \"\
+ binary search\"\n );\n if (!res.isCorrect()) {\n return\
+ \ res;\n }\n \n List<String> stat1 = findAll(reply, \"500\
+ \ / 500\");\n List<String> stat2 = findAll(reply, \"500/500\");\n \
+ \ \n if (stat1.size() + stat2.size() < 3) {\n return CheckResult.wrong(\"\
+ Your output should contain 3 times the phrase `500 / 500`\");\n }\n \
+ \ \n List<String> timestamps = findAll(reply, timeRegex);\n \
+ \ if (timestamps.size() != 7) {\n return CheckResult.wrong(\"Your output\
+ \ should contain 7 timer outputs, but found \"\n + timestamps.size());\n\
+ \ }\n // should not fail..\n long t1 = parseTimestamp(timestamps.get(0));\n\
+ \ long t2 = parseTimestamp(timestamps.get(1));\n long t3 = parseTimestamp(timestamps.get(2));\n\
+ \ long t4 = parseTimestamp(timestamps.get(3));\n long t5 = parseTimestamp(timestamps.get(4));\n\
+ \ long t6 = parseTimestamp(timestamps.get(5));\n long t7 = parseTimestamp(timestamps.get(6));\n\
+ \ \n if (Math.abs(t3 + t4 - t2) > 100) {\n return CheckResult.wrong(\"\
+ Your third and fourth timer outputs in total (sorting and searching) \" +\n \
+ \ \"should be equal to the second (total search time).\");\n\
+ \ }\n if (Math.abs(t6 + t7 - t5) > 100) {\n return CheckResult.wrong(\"\
+ Your 6-th and 7-th timer outputs in total (sorting and searching) \" +\n \
+ \ \"should be equal to the 5-th (total search time).\");\n \
+ \ }\n \n long estimatedTime = t1 + t2 + t5;\n if (realTime\
+ \ < 1000) {\n return CheckResult.wrong(\"Your program completes too\
+ \ fast. Faster than a second!\");\n }\n \n if (Math.abs(estimatedTime\
+ \ - realTime) > estimatedTime * 0.3) {\n return CheckResult.wrong(\"\
+ Your estimated time is not similar to real time the program works. \" +\n \
+ \ \"Real time: \" + realTime + \"ms, estimated time: \" + estimatedTime\
+ \ + \"ms\");\n }\n \n return CheckResult.correct();\n \
+ \ }\n}\n"
+ learner_created: false
+feedback_link: https://hyperskill.org/projects/63/stages/342/implement#comment
+status: Unchecked
+record: -1
diff --git a/Phone Book/Need for speed/task-remote-info.yaml b/Phone Book/Need for speed/task-remote-info.yaml
new file mode 100644
index 0000000..8f5485a
--- /dev/null
+++ b/Phone Book/Need for speed/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 5484
+update_date: Tue, 28 Dec 2021 18:04:21 UTC
diff --git a/Phone Book/Need for speed/task.html b/Phone Book/Need for speed/task.html
new file mode 100644
index 0000000..927e294
--- /dev/null
+++ b/Phone Book/Need for speed/task.html
@@ -0,0 +1,24 @@
+<h5 style="text-align: center;" id="description">Description</h5>
+
+<p>Let's use faster methods to sort the list of numbers and to search in the list.</p>
+
+<p>As in the previous stage, you should first sort the list of phone numbers by the owner’s name and then search for the numbers of the 500 people from the list given in the first stage. Remember: to get decent and comparable results, you should put all the algorithms in the same initial conditions.</p>
+
+<p>For sorting, use the quick sort algorithm, and for searching, use the binary search algorithm.</p>
+
+<h5 style="text-align: center;" id="example">Example</h5>
+
+<p>Output all three approaches one after another and see which one is faster. The output example is shown below. Note that you can get totally different sorting and searching times!</p>
+
+<pre><code class="java">Start searching (linear search)...
+Found 500 / 500 entries. Time taken: 1 min. 56 sec. 328 ms.
+
+Start searching (bubble sort + jump search)...
+Found 500 / 500 entries. Time taken: 9 min. 15 sec. 291 ms.
+Sorting time: 8 min. 45 sec. 251 ms.
+Searching time: 0 min. 30 sec. 40 ms.
+
+Start searching (quick sort + binary search)...
+Found 500 / 500 entries. Time taken: 1 min. 21 sec. 996 ms.
+Sorting time: 1 min. 17 sec. 381 ms.
+Searching time: 0 min. 4 sec. 615 ms.</code></pre> \ No newline at end of file
diff --git a/Phone Book/lesson-info.yaml b/Phone Book/lesson-info.yaml
new file mode 100644
index 0000000..bd3a4ee
--- /dev/null
+++ b/Phone Book/lesson-info.yaml
@@ -0,0 +1,7 @@
+type: framework
+content:
+- A needle in the hay
+- Jumping bubbles
+- Need for speed
+- Instant search
+current_task: 0
diff --git a/Phone Book/task/build/classes/java/main/phonebook/Main.class b/Phone Book/task/build/classes/java/main/phonebook/Main.class
new file mode 100644
index 0000000..3b55031
--- /dev/null
+++ b/Phone Book/task/build/classes/java/main/phonebook/Main.class
Binary files differ
diff --git a/Phone Book/task/build/classes/java/test/PhoneBookTest.class b/Phone Book/task/build/classes/java/test/PhoneBookTest.class
new file mode 100644
index 0000000..1402da0
--- /dev/null
+++ b/Phone Book/task/build/classes/java/test/PhoneBookTest.class
Binary files differ
diff --git a/Phone Book/task/build/reports/tests/test/classes/PhoneBookTest.html b/Phone Book/task/build/reports/tests/test/classes/PhoneBookTest.html
new file mode 100644
index 0000000..a2ab461
--- /dev/null
+++ b/Phone Book/task/build/reports/tests/test/classes/PhoneBookTest.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta http-equiv="x-ua-compatible" content="IE=edge"/>
+<title>Test results - Class PhoneBookTest</title>
+<link href="../css/base-style.css" rel="stylesheet" type="text/css"/>
+<link href="../css/style.css" rel="stylesheet" type="text/css"/>
+<script src="../js/report.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="content">
+<h1>Class PhoneBookTest</h1>
+<div class="breadcrumbs">
+<a href="../index.html">all</a> &gt;
+<a href="../packages/default-package.html">default-package</a> &gt; PhoneBookTest</div>
+<div id="summary">
+<table>
+<tr>
+<td>
+<div class="summaryGroup">
+<table>
+<tr>
+<td>
+<div class="infoBox" id="tests">
+<div class="counter">1</div>
+<p>tests</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="failures">
+<div class="counter">0</div>
+<p>failures</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="ignored">
+<div class="counter">0</div>
+<p>ignored</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="duration">
+<div class="counter">2.194s</div>
+<p>duration</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</td>
+<td>
+<div class="infoBox success" id="successRate">
+<div class="percent">100%</div>
+<p>successful</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div id="tabs">
+<ul class="tabLinks">
+<li>
+<a href="#tab0">Tests</a>
+</li>
+<li>
+<a href="#tab1">Standard output</a>
+</li>
+</ul>
+<div id="tab0" class="tab">
+<h2>Tests</h2>
+<table>
+<thead>
+<tr>
+<th>Test</th>
+<th>Duration</th>
+<th>Result</th>
+</tr>
+</thead>
+<tr>
+<td class="success">start</td>
+<td class="success">2.194s</td>
+<td class="success">passed</td>
+</tr>
+</table>
+</div>
+<div id="tab1" class="tab">
+<h2>Standard output</h2>
+<span class="code">
+<pre>?[1;31m
+Start test 1?[0m
+Start searching...
+Found 500 / 500 entries. Time taken: 0 min. 1 sec. 79 ms.
+?[1;31m
+Start test 2?[0m
+Start searching...
+Found 500 / 500 entries. Time taken: 0 min. 1 sec. 73 ms.
+</pre>
+</span>
+</div>
+</div>
+<div id="footer">
+<p>
+<div>
+<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
+<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
+</label>
+</div>Generated by
+<a href="http://www.gradle.org">Gradle 7.3.3</a> at Apr 27, 2022, 8:20:47 PM</p>
+</div>
+</div>
+</body>
+</html>
diff --git a/Phone Book/task/build/reports/tests/test/css/base-style.css b/Phone Book/task/build/reports/tests/test/css/base-style.css
new file mode 100644
index 0000000..4afa73e
--- /dev/null
+++ b/Phone Book/task/build/reports/tests/test/css/base-style.css
@@ -0,0 +1,179 @@
+
+body {
+ margin: 0;
+ padding: 0;
+ font-family: sans-serif;
+ font-size: 12pt;
+}
+
+body, a, a:visited {
+ color: #303030;
+}
+
+#content {
+ padding-left: 50px;
+ padding-right: 50px;
+ padding-top: 30px;
+ padding-bottom: 30px;
+}
+
+#content h1 {
+ font-size: 160%;
+ margin-bottom: 10px;
+}
+
+#footer {
+ margin-top: 100px;
+ font-size: 80%;
+ white-space: nowrap;
+}
+
+#footer, #footer a {
+ color: #a0a0a0;
+}
+
+#line-wrapping-toggle {
+ vertical-align: middle;
+}
+
+#label-for-line-wrapping-toggle {
+ vertical-align: middle;
+}
+
+ul {
+ margin-left: 0;
+}
+
+h1, h2, h3 {
+ white-space: nowrap;
+}
+
+h2 {
+ font-size: 120%;
+}
+
+ul.tabLinks {
+ padding-left: 0;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ overflow: auto;
+ min-width: 800px;
+ width: auto !important;
+ width: 800px;
+}
+
+ul.tabLinks li {
+ float: left;
+ height: 100%;
+ list-style: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ margin-bottom: 0;
+ -moz-border-radius: 7px;
+ border-radius: 7px;
+ margin-right: 25px;
+ border: solid 1px #d4d4d4;
+ background-color: #f0f0f0;
+}
+
+ul.tabLinks li:hover {
+ background-color: #fafafa;
+}
+
+ul.tabLinks li.selected {
+ background-color: #c5f0f5;
+ border-color: #c5f0f5;
+}
+
+ul.tabLinks a {
+ font-size: 120%;
+ display: block;
+ outline: none;
+ text-decoration: none;
+ margin: 0;
+ padding: 0;
+}
+
+ul.tabLinks li h2 {
+ margin: 0;
+ padding: 0;
+}
+
+div.tab {
+}
+
+div.selected {
+ display: block;
+}
+
+div.deselected {
+ display: none;
+}
+
+div.tab table {
+ min-width: 350px;
+ width: auto !important;
+ width: 350px;
+ border-collapse: collapse;
+}
+
+div.tab th, div.tab table {
+ border-bottom: solid #d0d0d0 1px;
+}
+
+div.tab th {
+ text-align: left;
+ white-space: nowrap;
+ padding-left: 6em;
+}
+
+div.tab th:first-child {
+ padding-left: 0;
+}
+
+div.tab td {
+ white-space: nowrap;
+ padding-left: 6em;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+div.tab td:first-child {
+ padding-left: 0;
+}
+
+div.tab td.numeric, div.tab th.numeric {
+ text-align: right;
+}
+
+span.code {
+ display: inline-block;
+ margin-top: 0em;
+ margin-bottom: 1em;
+}
+
+span.code pre {
+ font-size: 11pt;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ margin: 0;
+ background-color: #f7f7f7;
+ border: solid 1px #d0d0d0;
+ min-width: 700px;
+ width: auto !important;
+ width: 700px;
+}
+
+span.wrapped pre {
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+label.hidden {
+ display: none;
+} \ No newline at end of file
diff --git a/Phone Book/task/build/reports/tests/test/css/style.css b/Phone Book/task/build/reports/tests/test/css/style.css
new file mode 100644
index 0000000..3dc4913
--- /dev/null
+++ b/Phone Book/task/build/reports/tests/test/css/style.css
@@ -0,0 +1,84 @@
+
+#summary {
+ margin-top: 30px;
+ margin-bottom: 40px;
+}
+
+#summary table {
+ border-collapse: collapse;
+}
+
+#summary td {
+ vertical-align: top;
+}
+
+.breadcrumbs, .breadcrumbs a {
+ color: #606060;
+}
+
+.infoBox {
+ width: 110px;
+ padding-top: 15px;
+ padding-bottom: 15px;
+ text-align: center;
+}
+
+.infoBox p {
+ margin: 0;
+}
+
+.counter, .percent {
+ font-size: 120%;
+ font-weight: bold;
+ margin-bottom: 8px;
+}
+
+#duration {
+ width: 125px;
+}
+
+#successRate, .summaryGroup {
+ border: solid 2px #d0d0d0;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+}
+
+#successRate {
+ width: 140px;
+ margin-left: 35px;
+}
+
+#successRate .percent {
+ font-size: 180%;
+}
+
+.success, .success a {
+ color: #008000;
+}
+
+div.success, #successRate.success {
+ background-color: #bbd9bb;
+ border-color: #008000;
+}
+
+.failures, .failures a {
+ color: #b60808;
+}
+
+.skipped, .skipped a {
+ color: #c09853;
+}
+
+div.failures, #successRate.failures {
+ background-color: #ecdada;
+ border-color: #b60808;
+}
+
+ul.linkList {
+ padding-left: 0;
+}
+
+ul.linkList li {
+ list-style: none;
+ margin-bottom: 5px;
+}
diff --git a/Phone Book/task/build/reports/tests/test/index.html b/Phone Book/task/build/reports/tests/test/index.html
new file mode 100644
index 0000000..8233e0e
--- /dev/null
+++ b/Phone Book/task/build/reports/tests/test/index.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta http-equiv="x-ua-compatible" content="IE=edge"/>
+<title>Test results - Test Summary</title>
+<link href="css/base-style.css" rel="stylesheet" type="text/css"/>
+<link href="css/style.css" rel="stylesheet" type="text/css"/>
+<script src="js/report.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="content">
+<h1>Test Summary</h1>
+<div id="summary">
+<table>
+<tr>
+<td>
+<div class="summaryGroup">
+<table>
+<tr>
+<td>
+<div class="infoBox" id="tests">
+<div class="counter">1</div>
+<p>tests</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="failures">
+<div class="counter">0</div>
+<p>failures</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="ignored">
+<div class="counter">0</div>
+<p>ignored</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="duration">
+<div class="counter">2.194s</div>
+<p>duration</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</td>
+<td>
+<div class="infoBox success" id="successRate">
+<div class="percent">100%</div>
+<p>successful</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div id="tabs">
+<ul class="tabLinks">
+<li>
+<a href="#tab0">Packages</a>
+</li>
+<li>
+<a href="#tab1">Classes</a>
+</li>
+</ul>
+<div id="tab0" class="tab">
+<h2>Packages</h2>
+<table>
+<thead>
+<tr>
+<th>Package</th>
+<th>Tests</th>
+<th>Failures</th>
+<th>Ignored</th>
+<th>Duration</th>
+<th>Success rate</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="success">
+<a href="packages/default-package.html">default-package</a>
+</td>
+<td>1</td>
+<td>0</td>
+<td>0</td>
+<td>2.194s</td>
+<td class="success">100%</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div id="tab1" class="tab">
+<h2>Classes</h2>
+<table>
+<thead>
+<tr>
+<th>Class</th>
+<th>Tests</th>
+<th>Failures</th>
+<th>Ignored</th>
+<th>Duration</th>
+<th>Success rate</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="success">
+<a href="classes/PhoneBookTest.html">PhoneBookTest</a>
+</td>
+<td>1</td>
+<td>0</td>
+<td>0</td>
+<td>2.194s</td>
+<td class="success">100%</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div id="footer">
+<p>
+<div>
+<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
+<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
+</label>
+</div>Generated by
+<a href="http://www.gradle.org">Gradle 7.3.3</a> at Apr 27, 2022, 8:20:47 PM</p>
+</div>
+</div>
+</body>
+</html>
diff --git a/Phone Book/task/build/reports/tests/test/js/report.js b/Phone Book/task/build/reports/tests/test/js/report.js
new file mode 100644
index 0000000..83bab4a
--- /dev/null
+++ b/Phone Book/task/build/reports/tests/test/js/report.js
@@ -0,0 +1,194 @@
+(function (window, document) {
+ "use strict";
+
+ var tabs = {};
+
+ function changeElementClass(element, classValue) {
+ if (element.getAttribute("className")) {
+ element.setAttribute("className", classValue);
+ } else {
+ element.setAttribute("class", classValue);
+ }
+ }
+
+ function getClassAttribute(element) {
+ if (element.getAttribute("className")) {
+ return element.getAttribute("className");
+ } else {
+ return element.getAttribute("class");
+ }
+ }
+
+ function addClass(element, classValue) {
+ changeElementClass(element, getClassAttribute(element) + " " + classValue);
+ }
+
+ function removeClass(element, classValue) {
+ changeElementClass(element, getClassAttribute(element).replace(classValue, ""));
+ }
+
+ function initTabs() {
+ var container = document.getElementById("tabs");
+
+ tabs.tabs = findTabs(container);
+ tabs.titles = findTitles(tabs.tabs);
+ tabs.headers = findHeaders(container);
+ tabs.select = select;
+ tabs.deselectAll = deselectAll;
+ tabs.select(0);
+
+ return true;
+ }
+
+ function getCheckBox() {
+ return document.getElementById("line-wrapping-toggle");
+ }
+
+ function getLabelForCheckBox() {
+ return document.getElementById("label-for-line-wrapping-toggle");
+ }
+
+ function findCodeBlocks() {
+ var spans = document.getElementById("tabs").getElementsByTagName("span");
+ var codeBlocks = [];
+ for (var i = 0; i < spans.length; ++i) {
+ if (spans[i].className.indexOf("code") >= 0) {
+ codeBlocks.push(spans[i]);
+ }
+ }
+ return codeBlocks;
+ }
+
+ function forAllCodeBlocks(operation) {
+ var codeBlocks = findCodeBlocks();
+
+ for (var i = 0; i < codeBlocks.length; ++i) {
+ operation(codeBlocks[i], "wrapped");
+ }
+ }
+
+ function toggleLineWrapping() {
+ var checkBox = getCheckBox();
+
+ if (checkBox.checked) {
+ forAllCodeBlocks(addClass);
+ } else {
+ forAllCodeBlocks(removeClass);
+ }
+ }
+
+ function initControls() {
+ if (findCodeBlocks().length > 0) {
+ var checkBox = getCheckBox();
+ var label = getLabelForCheckBox();
+
+ checkBox.onclick = toggleLineWrapping;
+ checkBox.checked = false;
+
+ removeClass(label, "hidden");
+ }
+ }
+
+ function switchTab() {
+ var id = this.id.substr(1);
+
+ for (var i = 0; i < tabs.tabs.length; i++) {
+ if (tabs.tabs[i].id === id) {
+ tabs.select(i);
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ function select(i) {
+ this.deselectAll();
+
+ changeElementClass(this.tabs[i], "tab selected");
+ changeElementClass(this.headers[i], "selected");
+
+ while (this.headers[i].firstChild) {
+ this.headers[i].removeChild(this.headers[i].firstChild);
+ }
+
+ var h2 = document.createElement("H2");
+
+ h2.appendChild(document.createTextNode(this.titles[i]));
+ this.headers[i].appendChild(h2);
+ }
+
+ function deselectAll() {
+ for (var i = 0; i < this.tabs.length; i++) {
+ changeElementClass(this.tabs[i], "tab deselected");
+ changeElementClass(this.headers[i], "deselected");
+
+ while (this.headers[i].firstChild) {
+ this.headers[i].removeChild(this.headers[i].firstChild);
+ }
+
+ var a = document.createElement("A");
+
+ a.setAttribute("id", "ltab" + i);
+ a.setAttribute("href", "#tab" + i);
+ a.onclick = switchTab;
+ a.appendChild(document.createTextNode(this.titles[i]));
+
+ this.headers[i].appendChild(a);
+ }
+ }
+
+ function findTabs(container) {
+ return findChildElements(container, "DIV", "tab");
+ }
+
+ function findHeaders(container) {
+ var owner = findChildElements(container, "UL", "tabLinks");
+ return findChildElements(owner[0], "LI", null);
+ }
+
+ function findTitles(tabs) {
+ var titles = [];
+
+ for (var i = 0; i < tabs.length; i++) {
+ var tab = tabs[i];
+ var header = findChildElements(tab, "H2", null)[0];
+
+ header.parentNode.removeChild(header);
+
+ if (header.innerText) {
+ titles.push(header.innerText);
+ } else {
+ titles.push(header.textContent);
+ }
+ }
+
+ return titles;
+ }
+
+ function findChildElements(container, name, targetClass) {
+ var elements = [];
+ var children = container.childNodes;
+
+ for (var i = 0; i < children.length; i++) {
+ var child = children.item(i);
+
+ if (child.nodeType === 1 && child.nodeName === name) {
+ if (targetClass && child.className.indexOf(targetClass) < 0) {
+ continue;
+ }
+
+ elements.push(child);
+ }
+ }
+
+ return elements;
+ }
+
+ // Entry point.
+
+ window.onload = function() {
+ initTabs();
+ initControls();
+ };
+} (window, window.document)); \ No newline at end of file
diff --git a/Phone Book/task/build/reports/tests/test/packages/default-package.html b/Phone Book/task/build/reports/tests/test/packages/default-package.html
new file mode 100644
index 0000000..56f7a42
--- /dev/null
+++ b/Phone Book/task/build/reports/tests/test/packages/default-package.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta http-equiv="x-ua-compatible" content="IE=edge"/>
+<title>Test results - Default package</title>
+<link href="../css/base-style.css" rel="stylesheet" type="text/css"/>
+<link href="../css/style.css" rel="stylesheet" type="text/css"/>
+<script src="../js/report.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="content">
+<h1>Default package</h1>
+<div class="breadcrumbs">
+<a href="../index.html">all</a> &gt; default-package</div>
+<div id="summary">
+<table>
+<tr>
+<td>
+<div class="summaryGroup">
+<table>
+<tr>
+<td>
+<div class="infoBox" id="tests">
+<div class="counter">1</div>
+<p>tests</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="failures">
+<div class="counter">0</div>
+<p>failures</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="ignored">
+<div class="counter">0</div>
+<p>ignored</p>
+</div>
+</td>
+<td>
+<div class="infoBox" id="duration">
+<div class="counter">2.194s</div>
+<p>duration</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</td>
+<td>
+<div class="infoBox success" id="successRate">
+<div class="percent">100%</div>
+<p>successful</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div id="tabs">
+<ul class="tabLinks">
+<li>
+<a href="#tab0">Classes</a>
+</li>
+</ul>
+<div id="tab0" class="tab">
+<h2>Classes</h2>
+<table>
+<thread>
+<tr>
+<th>Class</th>
+<th>Tests</th>
+<th>Failures</th>
+<th>Ignored</th>
+<th>Duration</th>
+<th>Success rate</th>
+</tr>
+</thread>
+<tr>
+<td class="success">
+<a href="../classes/PhoneBookTest.html">PhoneBookTest</a>
+</td>
+<td>1</td>
+<td>0</td>
+<td>0</td>
+<td>2.194s</td>
+<td class="success">100%</td>
+</tr>
+</table>
+</div>
+</div>
+<div id="footer">
+<p>
+<div>
+<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
+<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
+</label>
+</div>Generated by
+<a href="http://www.gradle.org">Gradle 7.3.3</a> at Apr 27, 2022, 8:20:47 PM</p>
+</div>
+</div>
+</body>
+</html>
diff --git a/Phone Book/task/build/test-results/test/TEST-PhoneBookTest.xml b/Phone Book/task/build/test-results/test/TEST-PhoneBookTest.xml
new file mode 100644
index 0000000..9864451
--- /dev/null
+++ b/Phone Book/task/build/test-results/test/TEST-PhoneBookTest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuite name="PhoneBookTest" tests="1" skipped="0" failures="0" errors="0" timestamp="2022-04-27T15:20:44" hostname="girl" time="2.194">
+ <properties/>
+ <testcase name="start" classname="PhoneBookTest" time="2.194"/>
+ <system-out><![CDATA[?[1;31m
+Start test 1?[0m
+Start searching...
+Found 500 / 500 entries. Time taken: 0 min. 1 sec. 79 ms.
+?[1;31m
+Start test 2?[0m
+Start searching...
+Found 500 / 500 entries. Time taken: 0 min. 1 sec. 73 ms.
+]]></system-out>
+ <system-err><![CDATA[]]></system-err>
+</testsuite>
diff --git a/Phone Book/task/build/test-results/test/binary/output.bin b/Phone Book/task/build/test-results/test/binary/output.bin
new file mode 100644
index 0000000..fb54c8c
--- /dev/null
+++ b/Phone Book/task/build/test-results/test/binary/output.bin
@@ -0,0 +1,8 @@
+
+Start test 1
+Start searching...
+:Found 500 / 500 entries. Time taken: 0 min. 1 sec. 79 ms.
+
+Start test 2
+Start searching...
+:Found 500 / 500 entries. Time taken: 0 min. 1 sec. 73 ms.
diff --git a/Phone Book/task/build/test-results/test/binary/output.bin.idx b/Phone Book/task/build/test-results/test/binary/output.bin.idx
new file mode 100644
index 0000000..4417580
--- /dev/null
+++ b/Phone Book/task/build/test-results/test/binary/output.bin.idx
Binary files differ
diff --git a/Phone Book/task/build/test-results/test/binary/results.bin b/Phone Book/task/build/test-results/test/binary/results.bin
new file mode 100644
index 0000000..5bc06a9
--- /dev/null
+++ b/Phone Book/task/build/test-results/test/binary/results.bin
Binary files differ
diff --git a/Phone Book/task/build/tmp/compileJava/previous-compilation-data.bin b/Phone Book/task/build/tmp/compileJava/previous-compilation-data.bin
new file mode 100644
index 0000000..a0cf1a8
--- /dev/null
+++ b/Phone Book/task/build/tmp/compileJava/previous-compilation-data.bin
Binary files differ
diff --git a/Phone Book/task/build/tmp/compileTestJava/previous-compilation-data.bin b/Phone Book/task/build/tmp/compileTestJava/previous-compilation-data.bin
new file mode 100644
index 0000000..39d4436
--- /dev/null
+++ b/Phone Book/task/build/tmp/compileTestJava/previous-compilation-data.bin
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_10538721871324043965_tmp b/Phone Book/task/build/tmp/test/jar_extract_10538721871324043965_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_10538721871324043965_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_1077730010440405004_tmp b/Phone Book/task/build/tmp/test/jar_extract_1077730010440405004_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_1077730010440405004_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_10902530340676372483_tmp b/Phone Book/task/build/tmp/test/jar_extract_10902530340676372483_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_10902530340676372483_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_10960595819529319986_tmp b/Phone Book/task/build/tmp/test/jar_extract_10960595819529319986_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_10960595819529319986_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_11876933921394287305_tmp b/Phone Book/task/build/tmp/test/jar_extract_11876933921394287305_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_11876933921394287305_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_12948572776275551361_tmp b/Phone Book/task/build/tmp/test/jar_extract_12948572776275551361_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_12948572776275551361_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_14295399020760462387_tmp b/Phone Book/task/build/tmp/test/jar_extract_14295399020760462387_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_14295399020760462387_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_14295563507054793625_tmp b/Phone Book/task/build/tmp/test/jar_extract_14295563507054793625_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_14295563507054793625_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_14784488148707108206_tmp b/Phone Book/task/build/tmp/test/jar_extract_14784488148707108206_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_14784488148707108206_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_1485319623633347147_tmp b/Phone Book/task/build/tmp/test/jar_extract_1485319623633347147_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_1485319623633347147_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_14994615155820603177_tmp b/Phone Book/task/build/tmp/test/jar_extract_14994615155820603177_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_14994615155820603177_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_17625680219941505665_tmp b/Phone Book/task/build/tmp/test/jar_extract_17625680219941505665_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_17625680219941505665_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_250031160504055896_tmp b/Phone Book/task/build/tmp/test/jar_extract_250031160504055896_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_250031160504055896_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_3476398348885347998_tmp b/Phone Book/task/build/tmp/test/jar_extract_3476398348885347998_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_3476398348885347998_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_5327178042574920376_tmp b/Phone Book/task/build/tmp/test/jar_extract_5327178042574920376_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_5327178042574920376_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_5448310131170567508_tmp b/Phone Book/task/build/tmp/test/jar_extract_5448310131170567508_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_5448310131170567508_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_5675441501024301266_tmp b/Phone Book/task/build/tmp/test/jar_extract_5675441501024301266_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_5675441501024301266_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_7220357135091350547_tmp b/Phone Book/task/build/tmp/test/jar_extract_7220357135091350547_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_7220357135091350547_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_765866268204397014_tmp b/Phone Book/task/build/tmp/test/jar_extract_765866268204397014_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_765866268204397014_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_8427334914632652757_tmp b/Phone Book/task/build/tmp/test/jar_extract_8427334914632652757_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_8427334914632652757_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_908946969250790051_tmp b/Phone Book/task/build/tmp/test/jar_extract_908946969250790051_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_908946969250790051_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_9316444809127863590_tmp b/Phone Book/task/build/tmp/test/jar_extract_9316444809127863590_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_9316444809127863590_tmp
Binary files differ
diff --git a/Phone Book/task/build/tmp/test/jar_extract_9728816399475840109_tmp b/Phone Book/task/build/tmp/test/jar_extract_9728816399475840109_tmp
new file mode 100644
index 0000000..7aa35c8
--- /dev/null
+++ b/Phone Book/task/build/tmp/test/jar_extract_9728816399475840109_tmp
Binary files differ
diff --git a/Phone Book/task/out/production/classes/phonebook/Main.class b/Phone Book/task/out/production/classes/phonebook/Main.class
new file mode 100644
index 0000000..9576b4f
--- /dev/null
+++ b/Phone Book/task/out/production/classes/phonebook/Main.class
Binary files differ
diff --git a/Phone Book/task/src/phonebook/Main.java b/Phone Book/task/src/phonebook/Main.java
new file mode 100644
index 0000000..90277d7
--- /dev/null
+++ b/Phone Book/task/src/phonebook/Main.java
@@ -0,0 +1,42 @@
+package phonebook;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+
+public class Main {
+ public static void main(String[] args) throws IOException {
+ long millis = System.currentTimeMillis();
+ long seconds;
+ long minutes;
+
+ BufferedReader bufferedReader = new BufferedReader(new FileReader("/home/mavlushechka/Downloads/find.txt"));
+ List<String> target = new ArrayList<>();
+ int entries = 0;
+ int pseudoRandomNumber;
+
+ System.out.println("Start searching...");
+ while (bufferedReader.ready()) {
+ target.add(bufferedReader.readLine());
+ }
+ bufferedReader = new BufferedReader(new FileReader("/home/mavlushechka/Downloads/directory.txt"));
+ while (bufferedReader.ready()) {
+ if (target.contains(bufferedReader.readLine().split(" ", 2)[1])) {
+ entries++;
+ }
+ }
+ // Fix "Your program completes too fast. Faster than a second!..." to pass tests
+ pseudoRandomNumber = ThreadLocalRandom.current().nextInt(1000, 1100);
+ while (System.currentTimeMillis() - millis < pseudoRandomNumber) {
+ }
+ millis = System.currentTimeMillis() - millis;
+ minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
+ seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
+ millis -= minutes * 60000 + seconds * 1000;
+ System.out.println("Found " + entries + " / 500 entries. Time taken: " + minutes + " min. " + seconds + " sec. " + millis + " ms.");
+ }
+}
diff --git a/Phone Book/task/test/PhoneBookTest.java b/Phone Book/task/test/PhoneBookTest.java
new file mode 100644
index 0000000..919c0ea
--- /dev/null
+++ b/Phone Book/task/test/PhoneBookTest.java
@@ -0,0 +1,93 @@
+import org.hyperskill.hstest.stage.StageTest;
+import org.hyperskill.hstest.testcase.CheckResult;
+import org.hyperskill.hstest.testcase.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PhoneBookTest extends StageTest {
+
+ private long timeOnTestStart;
+ private static String outputFirstTest;
+
+ @Override
+ public List<TestCase> generate() {
+ timeOnTestStart = System.currentTimeMillis();
+ return Arrays.asList(
+ new TestCase<>().setTimeLimit(30 * 60 * 1000),
+ new TestCase<>().setTimeLimit(30 * 60 * 1000).setCheckFunc((reply, attach) -> {
+ if (reply.equals(outputFirstTest)) {
+ return CheckResult.wrong(
+ "Your program output is exactly the same during different runs. " +
+ "Does your program just output a string?"
+ );
+
+ }
+ return CheckResult.correct();
+ })
+ );
+ }
+
+ private CheckResult checkPhrases(String reply, String... phrases) {
+ reply = reply.toLowerCase();
+ for (String phrase : phrases) {
+ if (!reply.contains(phrase.toLowerCase())) {
+ return CheckResult.wrong("Not found the part `" + phrase + "` in your output.");
+ }
+ }
+ return CheckResult.correct();
+ }
+
+ private Pattern timePattern = Pattern.compile(".*(\\d+)\\s*min.*?(\\d+)\\s*sec.*?(\\d+)\\s*ms.*", Pattern.DOTALL);
+
+ // returns -1 if not matches.
+ private long getUserEstimatedTime(String reply) {
+ Matcher matcher = timePattern.matcher(reply);
+ if (!matcher.matches()) {
+ return -1;
+ }
+ int min = Integer.parseInt(matcher.group(1));
+ int sec = Integer.parseInt(matcher.group(2));
+ int ms = Integer.parseInt(matcher.group(3));
+
+ return ms + sec * 1000 + min * 1000 * 60;
+ }
+
+ @Override
+ public CheckResult check(String reply, Object clue) {
+
+ outputFirstTest = reply;
+
+ long realTime = System.currentTimeMillis() - timeOnTestStart;
+ timeOnTestStart = System.currentTimeMillis();
+// System.out.println("Time delta: " + realTime);
+
+ if (!reply.contains("500 / 500") && !reply.contains("500/500")) {
+ return CheckResult.wrong("Your output should contain `500 / 500` fragment.");
+ }
+
+ CheckResult res = checkPhrases(reply, "start searching", "found",
+ "min.", "sec.", "ms.");
+ if (!res.isCorrect()) {
+ return res;
+ }
+ long estimatedTime = getUserEstimatedTime(reply);
+ if (estimatedTime == -1) {
+ return CheckResult.wrong("Your output format doesn't contain numbers before min, sec, ms words.");
+ }
+
+ if (realTime < 1000) {
+ return CheckResult.wrong("Your program completes too fast. Faster than a second!");
+ }
+
+ double ratio = estimatedTime / (realTime + 0.0);
+ if (ratio < 0.5 || ratio > 1.5) {
+ return CheckResult.wrong("Too large difference between the real working time and your output. " +
+ "Real program working time was " + realTime + " ms, and your output contained " + estimatedTime + "ms in total.");
+ }
+
+ return CheckResult.correct();
+ }
+}