Малко помощ за решение на Astrological Digits


0

Здравейте колеги,

Честито Рождество Христово!

Написах авторско решение на задачата Astrological Digits, но изглежда имам проблем с типовете данни double и decimal и в BGcoder не мога да достигна повече от 50 точки. Ако някой може да ми даде съвет ще съм му много благодарен.

Ето и кода: https://github.com/IanyB/Variant-2/blob/master/Astrological%20Digits

Поздрави!




Отговори



5

Въобще не разбирам постовете в тази тема. Човекът очевидно иска да му помогнем с НЕГОВИЯ код. Мисля, че е достатъчно интелигентен ако иска друго решение или да види авторските (които са ни предоставени), или да отвори темата за всички домашни, където има множество предложени. Не виждам по какъв начин помагате със своите решения.

Така, сега, вместо да ти пусна моето решение, което е десетина реда с for, минаващ през char- овете, което можеш да откриеш в гореспоменатата тема, и по никакъв начин не би ти помогнало, тъй като ти си се бориш да си го решиш със собствената си идея, нека погледнем кода ти.

Веднага е очевидна грешката в логиката и основната причина да се чупи кода- образуването на сума от цифрите на числото само два пъти. Защото какво прави кода ти- сумира цифрите на числото веднъж, след това ако тази сума е по- голяма от 9, сумира цифрите на новата сума и дава отговор. Какво става, в случай че след втората сума отново получим число, по- голямо от 9? Нищо, то се отпечатва, а това е грешно. Можеш да го тестваш с 11 девятки, или числото 99999999999 (99 милиарда 999 милиона 999 хиляди 999), при което първата ти сума ще бъде равна на 11 * 9 = 99 и тъй като е по- голяма от 9, ще мине през втория цикъл, след което ще получи 2 * 9 = 18 и ще го изпечата. Но ние търсим астрологическата сума, по- малка от 9, което означава, че трябва да минем още веднъж цикъла и да получим 1 + 8 = 9 като отговор.

Сега си викаш "Лесно ще го оправя, ще му вкарам пак проверка дали е 9 и ще направя thirdSum!". Добре, а представи си че числото има 11111111111 (11 милиарда 111 милиона 111 хиляди 111) девятки. Тогава пак ще ти се счупи логиката и трябва да добавяш нов if и нов цикъл. В тази задача това няма как да се случи, тъй като имаме ограничение на входа от общо 600 цифри, т.е. ако добавиш нова проверка, може би ще изкараш 100/100 заради ограниченията. Но се замисли, не е ли това прекалено грешна логика, за да се мъча с нея?

Като изключим концептуалната грешка, ето ти няколко tip- а от мен за кода ти:

1. string one, two three, four, five 
-Много лошо именуване, не дават никаква идея за какво се ползват (това не е от голяма важност при задача, която се оценява автоматично и именуването не играе роля, но все пак помага и на теб да откриеш къде бъркаш, а и те учи на добра практика).

2. string number = Console.ReadLine();

        if (BigInteger.TryParse(number, out n))
        {
 
            one = Convert.ToString(n);
-Записваш входа в стринг, стрингa конвертираш в BigInteger, BigInteger- a конвертираш в стринг. ????? Местиш си парите от десния джоб в левия и обратно в десния. Защо не си седят парите в десния джоб, ако там ти трябват?
 
3.         for (int i = 0; i < number.Length; i++)
            {
                four = number.Substring(i, 1);
 
                if (BigInteger.TryParse(four, out nSecond))
                {
                    five = Convert.ToString(nSecond);
                    six = six + five;
                }
                else
                {
                    continue;
                }
            }
-continue; e напълно излишно, това е естествения ход на кода: АКО може да парсне, парсва, ако не може, продължава. Дали ще има continue или не, няма никакво значение. Else, в който не се случва нищо различно от код без else, можеш сам да се сетиш, че не ти трябва.
 
Виждаш, че и в случая, когато получиш вход тип "-99999.999999" отново ще получиш грешен отговор (18), тъй като и в долната част на кода ти имаш грешна логика.
 
И може би най- важното- реши какво ще правиш. Ако ще ползваш string, ползвай сумиране на char- овете му, ако ще ползваш BigInteger, ползвай делене на 10 и събиране на модул от 10 за всяка от цифрите му. В момента правиш пълно мазало- стринг, обръщаш в число, обръщаш в стринг, четеш стринг, обръщаш в цифра, събираш, обръщаш сума в стринг... Избери или едното или другото.
 
Помисли сам как ще стане, ако не се сетиш, прочети двата алгоритъма тук (ЧЕТИ, САМО АКО НЕ ИСКАШ САМ ДА СЕ СЕТИШ):
 
I. String:
 
        do
        {
            astroSum = 0;
 
            foreach (char ch in inputN)
            {
                astroSum += (ch - '0');
            }
            inputN = astroSum.ToString();
 
        } while (astroSum > 9);

Където inputN трябва да е парснат без '-' и '.', иначе трябва да вкараш допълнително проверката if (ch != '-' && ch != '.').
 

II. BigInteger:

        do
        {
            astroSum = 0;
 
            while (n > 0)
            {
                astroSum += n % 10;
                n /= 10;
            }
            n = astroSum;
 
        } while (astroSum > 9);
 
Където n трябва да е парснат към BigInteger без знаците '-' и '.'

от Anubis_Black (1521 точки)


0
Точно такъв коментар исках - някой да ми анализира кода и да ми "отвори очите". Много добре си описал всичко имаш едно голямо БЛАГОДАРЯ от мен! :-)

от IanyB (292 точки)

0
Няма проблеми, за това е форума. Успех със задачите!

от Anubis_Black (1521 точки)


0
Здравей!
Прегледай тази тема http://forums.academy.telerik.com/29909/ .
Лично аз ти препоръчвам да прегледаш и видеата от темата Подготовка за тест и изпит.
Идеята с double и decimal не е най-добрата и най-лесната за изпълнение и не съм убедена дали изобщо е възможно да даде 100/100. И аз така я мъчих първия път цял ден ;)
Весела Коледа!
Диди



0
Благодаря ти за информацията! Прегледал съм тази темата и аз останах с впечатлението, че не е възможно да даде 100/100, но бях длъжен да попитам. :-)

от IanyB (292 точки)

0
И аз се блъсках много време и не я докарах:)



2
Ами просто в случая независимо че в условието се говори за някакви десетични дроби, предвид че се иска да се работи с цифрите на числото (то ест не можем да си позволим загуба на цифри, което се случва с double и дори с decimal), по-удобно в случая е да се работи да речем със стрингове, в които да се съхраняват цифрите. Ето и моето решение на задачката, което дава 100 от 100:
http://pastebin.com/4BwgMxBs

от d_p_y (712 точки)


0
Браво колега! Решението ти ми харесва много! +1 Весела Коледа!

от IanyB (292 точки)

0
Радвам се, че съм помогнал :) Поздрави и весели празници! :)

от d_p_y (712 точки)


0

И аз се поборих малко с double, даже с BigInteger, но в крайна сметка реших, че няма да стане и сътворих кратичко решение с един цикъл и стринг: http://pastebin.com/xxKejucE

using System;
 
class AstrologicalDigits
{
    static void Main()
    {
        string Nstr = Console.ReadLine();
        int i = 0;
        int sum = 0;
        while (i < Nstr.Length)
        { 
            string digit = Nstr.Substring(i,1);
            if (digit != "." && digit != "-")
                sum = sum + int.Parse(digit);
            if (sum >= 10 && i == Nstr.Length - 1)
            {
                Nstr = Convert.ToString(sum);
                i = -1;
                sum = 0;
            }
            i++;
        }
        Console.WriteLine(sum);
    }
}

от shristoff (747 точки)


0
Виж тази тема: http://forums.academy.telerik.com/28299/bgcoder-telerik-academy-exam-1-2011-astrological-digits Виж видетото на Наков: http://www.youtube.com/watch?v=rP1Gq6O7VP0 Започва на 32-ра минута
В C# няма числен тип, който да събира реално число със 600 цифри, така че лично аз бих прочел числото, като стринг. Така и направих :D

от Mahata231 (1351 точки)


0
BigInteger ?? Събираш доста повече от 600 цифри :D Махаш десетичната точка от стринга и парсваш към BigInteger. Разбира се работа със стринга в случая е по-лесна :)

от westi3m (5621 точки)

0
ха.. тука ме финтира :D прав си .. не знам защо ама съм останал с едно такова впечатление, че нещо не му беше наред... но може и да си внушавам :D Edit: Сетих се... не съм се изразил правилно ... като въвеждаш числото го взимаш като стринг и после си го парсваш към каквото ти е удобно ... Няма тип който събира толкова големи реални числа ми беше мисълта. Ето защо съм останал с такова впечатление :D

от Mahata231 (1351 точки)


0
Здравей,
Честито Рождество Христово!
Аз я решавах с помощта на видеото от подготовката на Наков.
Ето го и решението.
http://pastebin.com/cfMw6LDk
Разгледай го. Работи на 100%.
Весели празници.

от Antoveravip (616 точки)


0

Благодаря на всички за съветите, които получих. Viktor Bahtev спомена за използването на BigInteger, после премахване на десетичната запетая и точно това направих.

Точките в BgCoder станаха 60/100, но не мога да открия защо не ми дава 100?

Не виждам грешка!

Ето новия код: https://github.com/IanyB/Variant-2/blob/master/Astrologiacal-Digits

 


от IanyB (292 точки)


0
Ето моето решение, с decimal и string и няколко научени неща от презентацията подготовка за изпит :). 100/100
using System; class AstrologicalDigits { static void Main(string[] args) {
string number = Console.ReadLine(); decimal astroNum = 0; bool result = decimal.TryParse(number,out astroNum);
while (number.Length > 1) { astroNum = 0; foreach (var item in number) { switch (item) { case '-': case '.': break; default: astroNum += (item - '0'); break; } } number = Convert.ToString(astroNum); } Console.WriteLine(astroNum); } }

от el_b_k (424 точки)


0

Ето още едно решение от мен без кастване:

 

using System;
 
class Program
{
    static void Main()
    {
        string stringNumber = Console.ReadLine();
        stringNumber = stringNumber.Replace(".""");
        stringNumber = stringNumber.Replace("-""");
        int sum = 0;
        for (int i = 0; i <  stringNumber.Length; i++)
        {
            sum += stringNumber[i] - 48;
        }
        while (sum > 9)
        {
            stringNumber = sum.ToString();
            sum = 0;
            for (int i = 0; i < stringNumber.Length; i++)
            {
                sum += stringNumber[i] - 48;
            }
        }
        Console.WriteLine(sum);
    }
}

от nikola76 (1250 точки)


0
/sigh /facepalm

от Anubis_Black (1521 точки)