Задача 5. C# Messages от More Exercise Introduction
Здравейте, може ли малко помощ на тази задача :
1.Messages
Write a program, which emulates typing an SMS, following this guide:
1 |
2 abc |
3 def |
4 ghi |
5 jkl |
6 mno |
7 pqrs |
8 tuv |
9 wxyz |
0 space |
Following the guide, 2 becomes “a”, 22 becomes “b” and so on.
Examples
Input |
Output |
|
Input |
Output |
|
Input |
Output |
5 44 33 555 555 666 |
hello |
9 44 33 999 0 8 44 33 777 33 |
hey there |
7 6 33 33 8 0 6 33 |
meet me |
Hints
- A native approach would be to just put all the possible combinations of digits in a giant switch statement.
- A cleverer approach would be to come up with a mathematical formula, which converts a number to its alphabet representation:
Digit |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Let’s take the number 222 (c) for example. Our algorithm would look like this:
- Find the number of digits the number has “e.g. 222 è 3 digits”
- Find the main digit of the number “e.g. 222 è 2”
- Find the offset of the number. To do that, you can use the formula: (main digit - 2) * 3
- If the main digit is 8 or 9, we need to add 1 to the offset, since the digits 7 and 9 have 4 letters each
- Finally, find the letter index (a è 0, c è 2, etc.). To do that, we can use the following formula: (offset + digit length - 1).
- After we’ve found the letter index, we can just add that to the ASCII code of the lowercase letter “a” (97)
И трите нулеви тестове минават, но след това се чупи някъде. Моля някой за малко съвет?
Направил съм я по стандартния начин с Switch case конструкция, като входните данни от конзолата първо се четяха като целочислени тип Integer, сега ги направих да са String, но отново същия резултат в Judge 20/100 точки.
Ето и кода: https://pastebin.com/tQtUbLey - Вариант със string
https://pastebin.com/jd1gR5nG - Вариант с Integer
Здравей,
да така е. Решавам я и по двата начина.
Първо реших да я напиша със знанията които имам до момента без да ползвам формулата, която е дадена в подсказката наготово, но още при първото ми решение резултата бе 20/100 точки - и зациклих.
Благодарение на колежката вече съм на 100/100 точки.
Сега започвам с втория вариант, който ти си посочил. Като цяло стъпките са ми ясни, но не схващам за какво е:
1. Main Digit - единиците ли се търсят или стотиците - т.е. с % деление ли го търсим къто остатък или с целичислено деление / за да намерим цялото числи.
2. Какво е offset - по скоро защо ни е? Каква е идеята на формулата (main digit - 2) * 3. Защо -2, защо *3;
3. If the main digit is 8 or 9, we need to add 1 to the offset, since the digits 7 and 9 have 4 letters each - тук може би има грешка в описанието - би трябвало ако основната цифра е 7 или 9, а не 8 или 9 според мен?
4. Каква е логиката на формулата
Много въпроси, но така ще е докато се науча :)
Поздрави,
Main Digit --> примерно 666, цифрата е 6.
Ако го обърнеш от int в string, string-а сам по себе си е масив от char-ове.
6 6 6
index 0 1 2
Когато вземеш елемента на нулевия индекс получаваш '6' но като char. Но според ASCII таблицата https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html десетичната стойност на този char е 54, а на '0' -> 48 (54 - 48 = 6).
За да го обърнеш към int по-лесно използваш:
int digit = digits[0] - '0';
Май си прав, че има грешка в условието сега го забелязах и аз, не се опитвай да задълбаваш толкова на тази задачка, вече сме на touch screen :D
Това с int digit = digits[0] - '0'; ми хареса. Умно измислено.
Докато схвана цялата логика ми отне известно време, но вече съм наясно каква е идеята, а за реализацията и варианти много.
Аз реших задачата по този начин:
using System;
namespace _05__Messages___difficult
{
class Program
{
static void Main(string[] args)
{
int countOfLetters = int.Parse(Console.ReadLine());
string word = string.Empty;
for (int i = 1; i <= countOfLetters; i++)
{
string currentDigit = Console.ReadLine(); //44
int mainDigit = int.Parse(currentDigit[0].ToString());
if (mainDigit == 8 || mainDigit == 9)
{
int offset = ((mainDigit - 2) * 3) + 1;
int offsetInSquare = currentDigit.Length;
int totalOffset = offset + offsetInSquare - 1;
char letter = (char)(97 + totalOffset);
word += letter;
}
else if (mainDigit == 0)
{
word += ' ';
}
else
{
int offset = (mainDigit - 2) * 3;
int offsetInSquare = currentDigit.Length;
int totalOffset = offset + offsetInSquare - 1;
char letter = (char)(97 + totalOffset);
word += letter;
}
}
Console.WriteLine(word);
}
}
}
Благодаря за помощта!
Здравей, ако можеш да обясниш логиката на формулите (main digit - 2) * 3 и (offset + digit length - 1), ще съм ти много благодарна, защото и аз си блъскам главата с тях.
Здравей,
относно (main digit - 2) * 3 - каква е презумцията - Тук търсим с колко позиции е изместен текущия символ спрямо началото. Търсим 2 неща - с колко основни символи е изместен спрямо първия символ и второ с колко символа е изместен в текущото квадратче. Ще се опитам с пример понеже надали ме разбираш.
Ако искаме символа ни да е "j" как се смята с формулата показана по-горе.
Първо гледаме Main Digit-a колко е - в случая е 5 т.е. (5-2)*3=3*3=9 - т.е. 9 символа са минали (a b c d e f g h i) преди да дойде квадратчето където се намира "j"
Ако клавиша 1 и той беше запълнене с букви (и то 3 на брой) тогава формулата щеше да е (5-1)*3
Ако буквите започваха от 3тата цифра формулата би била (5-3)*3=6 - защото символите ще бъдета само abc и d e f общо 6;
Сега трябва да разберем "j" на каква позиция е в самото квадратче, а те са 1 2 или 3 - "j" ни е на първа позиция вътре в квадратчето
Следователно прилагаме следващата формула (offset + digit length - 1) където offset ни е това изместване което намерихме сега, digit length ни е позицията на символа "j" вътре в квадратчето т.е. 1 позиция (ако беше k щеше да е 2ра позиция, ако беше L трета), а -1 се използва поради разбинаването на нашето броене и това как индексира символите компютъра например: String text = "Ivan" броя на буквите е 4бр (I-1, v-2, a-3, n-4) но като индексация започвайки от 0 се броят така (I-0, v-1, a-2, n-3)
В крайна сметка аз го разбрах този пример така: Представих си че трябва да индексирам цялата английска азбука от A до Z както е направено в таблицата горе. Символите са от от 1 до 26 (т.е общо 26бр) но индексите им са от 0 до 25 защото се включва и нулата (т.е отново са общо 26бр)
Така де но ако не са разделени на групи от по 3 символа за да изпиша Z трябва да натисна клавиша 26 пъти, за Х 24 пъти, а това ще е доста трудно за изписване на цял SMS със сто символа. И от тук е идеята да се раздели на блокове от по 3 (или 4) символа в блок, да се намери колко блока с по колко символа в този блок има преди символа който искаме да изпишем и това е решението.
Поздрави,
Много благодаря за изчерпателния отговор, всичко ми се изясни. :)
Радвам се.
Успех!