Премини към съдържанието
Форумът в приложение

По-лесно сърфиране. Научи повече.

Kaldata.com - Форуми

Приложение на форума на цял екран с push известия, значки и други.

За да инсталирате това приложение на iOS и iPadOS
  1. Докоснете Иконата за споделяне в Safari
  2. Превъртете менюто и докоснете Добавяне към началния екран.
  3. Докоснете Добавяне в горния десен ъгъл.
За да инсталирате това приложение на Android
  1. Докоснете менюто с 3 точки (⋮) в горния десен ъгъл на браузъра.
  2. Докоснете Добавяне към началния екран или Инсталиране на приложение.
  3. Потвърдете, като докоснете Инсталиране.

Добре дошли!

Добре дошли в нашите форуми, пълни с полезна информация. Имате проблем с компютъра или телефона си? Публикувайте нова тема и ще намерите решение на всичките си проблеми. Общувайте свободно и открийте безброй нови приятели.

Моля, регистрирайте се за да публикувате тема и да получите пълен достъп до всички функции.

 

C++ задача

Featured Replies

Да се състави програма, която въвежда от клавиатурата естествено число k. Програмата да извежда всички трицифрени числа, сумата от цифрите на които е равна на числото k.

Ако някой може да ми помогне с идея или направо решението на задачата ще съм му много благодарен :)

#include<iostream.h>
#include<conio.h>
int main()
{
int k;
while (k < 0 || k > 999)
cout << "Input k (0-999): ";
cin >> k;
for (int i = 0; i >= 999; i++)

преди 44 минути, NitnelavBG написа:

 

Да се състави програма, която въвежда от клавиатурата естествено число k. Програмата да извежда всички трицифрени числа, сумата от цифрите на които е равна на числото k.

 

Ако някой може да ми помогне с идея или направо решението на задачата ще съм му много благодарен :)

Windows:

#include <iostream>
using namespace std;
int main () {
int k,br=0;
cout <<"Въведете k: ";
cin >>k;
cout <<"k="<<k<<endl;
for (int i=100;i<1000;i++) {
int a = i / 100;
int b = (i % 100)/10;
int c = (i % 100) % 10;
if (a + b + c == k)
{
cout << i << "\n";
br++;
}
}
if (br==0) cout <<"Няма такива трицифрени числа\n";
system ("pause");
return 0;
}

_________________________________________________________________

Linux:

#include <iostream>
using namespace std;
int main () {
int k,br=0;
cout <<"Въведете k: ";
cin >>k;
cout <<"k="<<k<<endl;
for (int i=100;i<1000;i++) {
int a = i / 100;
int b = (i % 100)/10;
int c = (i % 100) % 10;
if (a + b + c == k)
{
cout << i << "\n";
br++;
}
}
if (br==0) cout <<"Няма такива трицифрени числа\n";
return 0;
}

#include <iostream>

using namespace std;

int main()
{
    int k;
    cout<<"K = ";
    cin >>k;
    if (k<1||k>27) 
    {
        cout<<"No such numbers\n"; 
        return 1;
    }
    
    for (int a=1; a<10; ++a)
        for (int b=0; b<10; ++b)
        {
            int c=k-a-b;
            if (c>=0&&c<10) 
                cout<<a<<b<<c<<endl;
        }
}

 

Редактирано от ined (преглед на промените)

преди 13 часа, ined написа:

...

Проверка до 18? Освен това към момента в който знаеш първата цифра, т.е. в началото на първия цикъл, можеш да определиш по-точно възможните граници на b, така че само да печаташ във вътрешния цикъл. Нещо такова:

    for (int a=1; a<10; ++a)
    {
        int c = 0;
        int d = 10;
        if (k - a >= 9)
          c = k - a - 9;
      	else
          d = k - a + 1;
        for (int b=c; b<d; ++b)
          cout<<a<<b<<k - a - b<<endl;
    }

 

Редактирано от flare (преглед на промените)

#include <stdio.h>

int main()
{
	int k, a, b, c;
	printf("k = ");
	scanf("%d", &k);
	if ((k < 1) || (k>27))
	{
		printf("There are no such numbers");
		return 1;
	}
	for (a = 1; a < 10; a++)
	{
		if (k < a) return 0;
		if (k > a + 18) continue;
		for (b = 0; b < 10; b++)
		{
			if (k < a + b) goto r;
			if (k > a + b + 9) continue;
			printf("%d%d%d\n", a, b, k - a - b);
		}
	r:;
	}
	return 0;
}

Понякога с goto е все едно, че му говориш на компютъра на български и те разбира !

преди 12 минути, Реджеп Иведик написа:

#include <stdio.h>

int main()
{
	int k, a, b, c;
	printf("k = ");
	scanf("%d", &k);
	if ((k < 1) || (k>27))
	{
		printf("There are no such numbers");
		return 1;
	}
	for (a = 1; a < 10; a++)
	{
		if (k < a) return 0;
		if (k > a + 18) continue;
		for (b = 0; b < 10; b++)
		{
			if (k < a + b) goto r;
			if (k > a + b + 9) continue;
			printf("%d%d%d\n", a, b, k - a - b);
		}
	r:;
	}
	return 0;
}

Понякога с goto е все едно, че му говориш на компютъра на български и те разбира !

1. Абсолютно безсмислено да ползваш gotо, след като това което искаш да направиш е break.
2. Първия if няма смисъл да се прави във цикъла, но е добра идея да му се сложи като ограничение - не бях се сетил.
3. Другото не е по-добро от това на @ined а е бая по-грозно. Основната идея беше да се избяга от много проверки във вътрешния цикъл.
 

По грозно е, ама не е по грозно. Инед ги върти и двата цикъла като поп. Разбираш ли ?

А аз прескачам по голямата част. 

И от твоето е по красиво, щото е по четливо. И е по лесно да се напише и разбере от човек. Вие ги увъртате, усуквате, съкращавате, и пак твърдите, че пишете четливо.

За break, бях забравил. Но goto не е по грозно. Ако беше безсмислено, великият Ричи нямаше да го измисли.

Освен това, в моя вариант, не стига, че се прескача голяма част от циклите, ми се работи и с по малко променливи. Туй "c" дето съм го декларирал е излишно, ма забравих да го махна.

Редактирано от Реджеп Иведик (преглед на промените)

преди 31 минути, Реджеп Иведик написа:

По грозно е, ама не е по грозно. Инед ги върти и двата цикъла като поп. Разбираш ли ?

А аз прескачам по голямата част. 

И от твоето е по красиво, щото е по четливо. И е по лесно да се напише и разбере от човек. Вие ги увъртате, усуквате, съкращавате, и пак твърдите, че пишете четливо.

За break, бях забравил. Но goto не е по грозно. Ако беше безсмислено, великият Ричи нямаше да го измисли.

Освен това, в моя вариант, не стига, че се прескача голяма част от циклите, ми се работи и с по малко променливи. Туй "c" дето съм го декларирал е излишно, ма забравих да го махна.

Моето е с абсолютно линейно изпълнение, като изключим циклите,  докато твоето скача нагоре надолу, като добавим и това за което ме подсети, ще стане и бая по-ефективно.

goto не го е измислил Ричи, ама човекът вероятно се обръща в гроба като вижда как го ползваш. Забележи, че не съм казвал никъде че изобщо не трябва да се ползва, а критикувам конкретната употреба.

Репликата за прескачането на променливи е игра на дребно. Едни 8 байта са нищо, а и почти сигурно ще бъдат в регистрите. Ако искаш може да компилираме и да гледаме асемблер :)

Ето ти и просто сравнение за четимост - аз имам един if, @ined има един if, като неговото е директното решение, дето идва на ума и като такова е още по-лесно за разбиране, при моето трябва да се зачудиш малко повече за втория цикъл. Ти имаш 4 if-a, които всеки прецаква цикъла в който се намира, което по дефиниция затруднява проследяването на логиката.

Редактирано от flare (преглед на промените)

преди 10 минути, flare написа:

Моето е с абсолютно линейно изпълнение, като изключим циклите,  докато твоето скача нагоре надолу, като добавим и това за което ме подсети, ще стане и бая по-ефективно.

goto не го е измислил Ричи, ама човекът вероятно се обръща в гроба като вижда как го ползваш. Забележи, че не съм казвал никъде че изобщо не трябва да се ползва, а критикувам конкретната употреба.

Репликата за прескачането на променливи е игра на дребно. Едни 8 байта са нищо, а и почти сигурно ще бъдат в регистрите. Ако искаш може да компилираме и да гледаме асемблер :)

А, с асемблер ще ме плашиш. Че аз мога да я напиша на асемблер. И като как изглежда асемблерска програма без джампове а ?

Има и с иф и уайл, ама то са макроси, разбираш ли ? Като се приведе на асемблер всичко е с jump, което е все едно goto. Аз асемблера съм го измислил

Няма голямо значение дали прескача или е линеен, на компютъра му е все едно.

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

А моят се лее, както се леят на човек мислите.

Редактирано от Реджеп Иведик (преглед на промените)

току-що, Реджеп Иведик написа:

А, с асемблер ще ме плашиш. Че аз мога да я напиша на асемблер. И като как изглежда асемблерска програма без джампове а ?

Има и с иф, ама то са макроси, разбираш ли ? Като се приведе на асемблер всичко е с jump, което е все едно goto. Аз асемблера съм го измислил

Избщо  не разбра какво искам да кажа. Идеята на добре написана програма на език от високо ниво е хем да се чете лесно, хем да изкара оптимален асемблер. Това което исках да кажа е, че моята версия няма да ползва повече памет от твоята а променливите не затрудняват самото четене, защото те много очевидно се ползват само за граници на цикъла. Прочети ми добавката в горния пост за сравнението за четимост.

преди 1 минута, flare написа:

Избщо  не разбра какво искам да кажа. Идеята на добре написана програма на език от високо ниво е хем да се чете лесно, хем да изкара оптимален асемблер. Това което исках да кажа е, че моята версия няма да ползва повече памет от твоята а променливите не затрудняват самото четене, защото те много очевидно се ползват само за граници на цикъла. Прочети ми добавката в горния пост за сравнението за четимост.

А моите ифове помагат навреме да се прескочи цикъла, или както е в случая с първия иф в първия цикъл, директно да се излезе от програмата. В моя вариант, този return в края на програмата е почти само за украса. Май има един два варианта в които кодът го удря, но дотам.

Какво прецакване на логиката е директното излизане от програмата ?

Втория иф в първия цикъл директно обезсмисля втория цикъл и за това го прескачам. Къде е тука сложното. И като е сложно, как го разбра.

За генерирания асемблерски код, може и да си прав. Може да си прав и за другото. 

Най оптимален код и на високо ниво и на асемблер изкарва брутфорса

преди 1 час, Реджеп Иведик написа:

Най оптимален код и на високо ниво и на асемблер изкарва брутфорса

#include <iostream>
#include <time.h>

int main()
{
  int x = 0, y = 0;
  clock_t t1,t2,t3;
  t1 = clock();
  for(int tt = 0; tt < 1000; tt++)
    for (int k = 1; k < 27; k++) {
      int m = k < 9 ? k+1 : 10;
      for (int a = 1; a < m; ++a) {
        int c = 0;
        int d = 10;
        if (k - a >= 9)
          c = k - a - 9;
        else
          d = k - a + 1;
        for (int b = c; b < d; ++b)
          x++;
      }
    }
  t2 = clock();
  for(int tt = 0; tt < 1000; tt++)
    for (int k = 1; k < 27; k++) {
      for (int a = 1; a < 10; a++)
      {
        if (k < a) break;
        if (k > a + 18) continue;
        for (int b = 0; b < 10; b++)
        {
          if (k < a + b) goto r;
          if (k > a + b + 9) continue;
          y++;
        }
        r:;
      }
    }
  t3 = clock();
  std::cout << (float)t2 - (float)t1 << " " << (float)t3 - (float)t2 << std::endl;
  std::cout << x << " " << y << std::endl;
}

Ето ти малко мерки и теглилки. На моя комп, първото с О0 дава над 2 пъти по-добро време а с O2 - 5-6 пъти. Заместил съм принтовете, защото са много бавни, спрямо останалото с инкрементиране. Това е валидно, защото са еднакви, т.е. и двамата печатаме a, b и k - a - b. Ограничаването на първия цикъл с променливата m, за което ти ми даде идея, дава 10-15%, ама и без нея съм доста по-добре.

Редактирано от flare (преглед на промените)

преди 24 минути, flare написа:

Ето ти малко мерки и теглилки.

Виж се сега какво си цитирал и какво ми отговаряш. 

Иначе схванах идеята. Благодаря. Входната променлива трябва да се оцени преди циклите.

преди 7 минути, Реджеп Иведик написа:

Виж се сега какво си цитирал и какво ми отговаряш. 

Иначе схванах идеята. Благодаря. Входната променлива трябва да се оцени преди циклите.

Цитирах изказване за оптималността на брутфорса и показвам как четливо написано кодче е достатъчно ефективно, че даже е и по-податливо на оптимизация.

а иначе естествено - ако нещо може да се направи извън цикъл, по-добре и по-ефективно е да е извън цикъла. А за break, continue и goto, обикновено е по-лесно да се чете код, в който for циклите си извъртат повторенията, не да се прекъсват, особено на няколко места. И като следствие (и моят опит го потвърждава) мога да кажа, че грешките много зачестяват в зоните, в които се срещат тези тричките.

преди 6 минути, flare написа:

Цитирах изказване за оптималността на брутфорса

Значи не си разбрал изказването. В какъв смисъл е по оптимален. Аз никога не си мисля, че това, което пиша е вярно във всички контексти, и за това ми е лесно да разбирам и да пиша разбрано.

Освен това е ясно, че ако избегнем всички проверки и оценки, и извъртим всички цикли без да ги прекъсваме, получаваме чист стопроцентов брутфорс, за което и намеквам с това изказване.

for (int k = 1; k < 27; k++) {
      int l = k > 19 ? k-18 : 1;
      int m = k < 9  ? k+1 : 10;
      for (int a = l; a < m; ++a) {
        int c = 0;
        int d = 10;
        if (k - a >= 9)
          c = k - a - 9;
        else
          d = k - a + 1;
        for (int b = c; b < d; ++b)
          x++;
      }
    }

Само не знам как автора на темата би успял да я обясни на даскала :)

  • Автор
току-що, ined написа:

for (int k = 1; k < 27; k++) {
      int l = k > 19 ? k-18 : 1;
      int m = k < 9  ? k+1 : 10;
      for (int a = l; a < m; ++a) {
        int c = 0;
        int d = 10;
        if (k - a >= 9)
          c = k - a - 9;
        else
          d = k - a + 1;
        for (int b = c; b < d; ++b)
          x++;
      }
    }

Само не знам как автора на темата би успял да я обясни на даскала :)

Имам време да го обмислям :ДДДД

преди 18 минути, ined написа:

      int l = k > 19 ? k-18 : 1;

 

Ама съм заспал днес. :D

  • Автор
преди 23 часа, FR13ND написа:

Linux:

#include <iostream>
using namespace std;
int main () {
int k,br=0;
cout <<"Въведете k: ";
cin >>k;
cout <<"k="<<k<<endl;
for (int i=100;i<1000;i++) {
int a = i / 100;
int b = (i % 100)/10;
int c = (i % 100) % 10;
if (a + b + c == k)
{
cout << i << "\n";
br++;
}
}
if (br==0) cout <<"Няма такива трицифрени числа\n";
return 0;
}

Много Ви благодаря. Ще използвам това, защото ми е най-лесно като идея, а и съм още начинаещ в програмирането като цяло. Лека вечер :)

#include <iostream>
using namespace std;


int main()
{
	int a, b, k, x, y;
	cout << "k = ";
	cin >> k;
	if ((k < 1) || (k > 27))
	{
		cout << "There are no such numbers";
		return 1;
	}
	if (k < 10)
	{
		for (a = 1; a <= k; a++)
		{
			x = k - a;
			for (b = 0; b <= x; b++)
			{
				cout << a << b << k - a - b << endl;
			}
		}
	}
	else if (k < 19)
	{
		for (a = 1; a < 10; a++)
		{
			x = k - a - 9;
			if (x < 0) x = 0;
			y = k - a;
			if (y > 9) y = 9;
			for (b = x; b <= y; b++)
			{
				cout << a << b << k - a - b << endl;
			}
		}
	}
	else
	{
		y = k - 18;
		for (a = y; a < 10; a++)
		{
			x = k - a - 9;
			for (b = x; b < 10; b++)
			{
				cout << a << b << k - a - b << endl;
			}
		}
	}
	return 0;
}

От това по бързо нема !!!

И хем няма goto, хем е четливо и красиво

Залагам на мойто

И хем идеята е чисто поднесена. Даже няма нужда от коментари

преди 8 часа, ined написа:

for (int k = 1; k < 27; k++) {
      int l = k > 19 ? k-18 : 1;
      int m = k < 9  ? k+1 : 10;
      for (int a = l; a < m; ++a) {
        int c = 0;
        int d = 10;
        if (k - a >= 9)
          c = k - a - 9;
        else
          d = k - a + 1;
        for (int b = c; b < d; ++b)
          x++;
      }
    }

Само не знам как автора на темата би успял да я обясни на даскала :)

Ще му пише двойка заради вас. Барем му кажи, че не е по условието.

Не е казано за всяко "К", Флеър го въведе за да си ги мерим. И теглим.

По условие е за произволно въведено "К"

Редактирано от Реджеп Иведик (преглед на промените)

Архивирана тема

Темата е твърде стара и е архивирана. Не можете да добавяте нови отговори в нея, но винаги можете да публикувате нова тема, в която да продължи дискусията. Регистрирайте се или влезте във вашия профил за да публикувате нова тема.

Разглеждащи това в момента 0

  • Няма регистрирани потребители разглеждащи тази страница.

Дарение

  • Подкрепи съществуването на форума - направи дарение
    32%
    Дарени 315 € от нужните 1 000 €

Бюлетин

Получавайте известие, когато има важна промяна или новина свързана с форума.

Профил

Навигация

Търсене

Търсене

Конфигуриране на push известия в браузъра

Chrome (Android)
  1. Докоснете иконата на катинар до адресната лента.
  2. Докоснете Разрешения → Известия.
  3. Променете предпочитанията си.
Chrome (Desktop)
  1. Кликнете върху иконата на катинар в адресната лента.
  2. Изберете Настройки на сайта.
  3. Намерете Известия и коригирайте предпочитанията си.