Re[2]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 20:05
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Аноним, Вы писали:


А>>Как вывести строку текста 1000 раз не используя явного или не явного цикла ?


К>Решение с рекурсией. Голый Си.

К>
К>#include <stdio.h>

К>void print_1() { printf("text\n"); }

К>#define DEF_PRINT(x,y) void print_##x() { print_##y(); print_##y(); }
К>DEF_PRINT(2,1)
К>DEF_PRINT(4,2)
К>DEF_PRINT(8,4)
К>DEF_PRINT(16,8)
К>DEF_PRINT(32,16)
К>DEF_PRINT(64,32)
К>DEF_PRINT(128,64)
К>DEF_PRINT(256,128)
К>DEF_PRINT(512,256)

К>int main()
К>{
К>  int const n = 1000;
К>  // мне лень раскладывать n по битам...
К>#define PRINT(x) (n & x) ? print_##x() : (void)0;
К>  PRINT(512);
К>  PRINT(256);
К>  PRINT(128);
К>  PRINT(64);
К>  PRINT(32);
К>  PRINT(16);
К>  PRINT(8);
К>  PRINT(4);
К>  PRINT(2);
К>  PRINT(1);
К>}
К>


Вы уже обьявленны победителем ! Смотрите чуть выше в ветке !
Re[3]: Тест на смекалку !
От: shank  
Дата: 25.03.06 20:13
Оценка: +1
Здравствуйте, 8bit, Вы писали:
Не умаляя заслуги Кодта, но все же, эта строчка
X say[1000];

транслируется в цикл с вызовом конструкторов...
Кто мог знать, что это уже не подпадает под определение "неявный цикл"?
Re[4]: Тест на смекалку !
От: Максим Грин Россия http://www.spektr.info.
Дата: 25.03.06 20:17
Оценка:
protestuu, moi variant s rekursivnim vizovom na golom si — to ze samoe
Re[4]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 20:22
Оценка:
Здравствуйте, shank, Вы писали:

S>Здравствуйте, 8bit, Вы писали:

S>Не умаляя заслуги Кодта, но все же, эта строчка
S>
S>X say[1000];
S>

S>транслируется в цикл с вызовом конструкторов...
S>Кто мог знать, что это уже не подпадает под определение "неявный цикл"?

Вот декомпиляция.
Цикл есть, который создал компилятор а не программист (причем конструктора нет) !
Задача была в том что бы программист не создавал руками цикла !

.text:004010C0 push esi
.text:004010C1 push edi
.text:004010C2 mov edi, ds:??6std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<(std::basic_ostream<char,std::char_traits<char>> &,char const *)
.text:004010C8 mov esi, 3E8h
.text:004010CD
.text:004010CD loc_4010CD: ; CODE XREF: _main+25j
.text:004010CD mov eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:004010D2 push offset aTest ; "test"
.text:004010D7 push eax
.text:004010D8 call edi ; std::operator<<(std::basic_ostream<char,std::char_traits<char>> &,char const *) ; std::operator<<(std::basic_ostream<char,std::char_traits<char>> &,char const *)
.text:004010DA push eax
.text:004010DB call ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:004010E1 add esp, 0Ch
.text:004010E4 dec esi
.text:004010E5 jnz short loc_4010CD
.text:004010E7 pop edi
.text:004010E8 xor eax, eax
.text:004010EA pop esi
.text:004010EB retn
Re[5]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 20:24
Оценка:
Здравствуйте, Максим Грин, Вы писали:

МГ>protestuu, moi variant s rekursivnim vizovom na golom si — to ze samoe


Рекурсия — это не явный цикл который создал программист....
Re[5]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 20:29
Оценка:
Здравствуйте, Максим Грин, Вы писали:

МГ>protestuu, moi variant s rekursivnim vizovom na golom si — to ze samoe


вот ваш счетчик не явного цикла, его создали вы своими же руками:
static int c = 1000;
if (--c)
Re[2]: ЕСТЬ ПОБЕДИТЕЛЬ !
От: 8bit  
Дата: 25.03.06 20:35
Оценка:
А так же 'sc', знавший ответ, но умолчал дабы было интересно...
Re[5]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 20:39
Оценка:
звиняйте.... конструктор конечно же есть....
Но главное что программист не создавал руками цикла !
Re[2]: ЕСТЬ ПОБЕДИТЕЛЬ !
От: Кодт Россия  
Дата: 25.03.06 20:43
Оценка: +1
Здравствуйте, 8bit, Вы писали:

8>это и есть решение без цикла, явного или не явного, с наименьшим количеством кода !


Это решение — не совсем "чистый" С++, поскольку пришлось определить свой класс.
Чистое решение — вот:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
  std::fill_n(std::ostream_iterator<const char*>(std::cout, "\n"), 1000, "hello!");
}

Ни одной нестандартной функции, ни одного нестандартного класса.

Ну а то, что fill_n неявно содержит цикл — так ведь и конструктор массива содержит цикл.
Перекуём баги на фичи!
Re[3]: ЕСТЬ ПОБЕДИТЕЛЬ !
От: 8bit  
Дата: 25.03.06 20:55
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, 8bit, Вы писали:


8>>это и есть решение без цикла, явного или не явного, с наименьшим количеством кода !


К>Это решение — не совсем "чистый" С++, поскольку пришлось определить свой класс.

К>Чистое решение — вот:
К>
К>#include <iostream>
К>#include <iterator>
К>#include <algorithm>
К>int main()
К>{
К>  std::fill_n(std::ostream_iterator<const char*>(std::cout, "\n"), 1000, "hello!");
К>}
К>

К>Ни одной нестандартной функции, ни одного нестандартного класса.

К>Ну а то, что fill_n неявно содержит цикл — так ведь и конструктор массива содержит цикл.


"чистый" С++ я употребил что бы люди не пытались использовать всякие там BOOST, рекурсии, а так же как намек что решение скрывается в одной из основ языка (конструктуре).

То что констуктор массива содержит цикл не относится к формулировке задачи, так как
програмист его не создает этот цикл, а только обьявляет массив. Т.е. этот цикл не 'рукотворный' если можно так выразиться. Это зависит от компилятора.
Re: Тест на смекалку !
От: Кодт Россия  
Дата: 25.03.06 20:56
Оценка: +1
Здравствуй, 8bit

У тебя, конечно же, было готово "правильное" решение. Поэтому ты закрываешь глаза на варианты. А этюд тем и интересен, чтобы решить его нестандартными способами. Это будет откровением для решающих — но и задавший задачу не должен в этом обделять ни себя, ни других.

С учётом того, что boost рискует войти в следующую версию Стандарта — BOOST_PP можно практически принять за решение.

Встречный вопрос к тебе: какими ещё способами можно решить твою задачу, кроме уже перечисленных?
— цикл
— препроцессор
— рекурсивные шаблоны
— дерево вызовов функций
— массив объектов, конструкторы с побочным эффектом
— std::fill_n + ostream_iterator

Несколько решений напрашиваются сразу.
И ещё одно решение может оказаться неочевидным Посмотрим — угадаешь ли ты, что я имею в виду.
Перекуём баги на фичи!
Re[2]: Тест на смекалку !
От: sc Россия  
Дата: 25.03.06 21:04
Оценка:
Здравствуйте, Кодт, Вы писали:
...
К>- массив объектов, конструкторы с побочным эффектом
...
и деструкторы тоже)
Re[3]: Тест на смекалку !
От: Кодт Россия  
Дата: 25.03.06 22:10
Оценка:
Здравствуйте, sc, Вы писали:

К>>- массив объектов, конструкторы с побочным эффектом

sc>и деструкторы тоже)

Замечательно. Одно из.

Какие ещё решения можно вписать в наши анналы? Ограничение на предельную простоту снято.

Есть ограничение на громоздкость: каждое решение должно быть минимально в своём классе.

Например, логарифмическая рекурсия в шаблонах — по основанию 2 упомянули, этого достаточно. По основанию 3 или 10 уже будет, во-первых, повтором, а во-вторых, более громоздко.
Линейная рекурсия в шаблонах — отдельный класс решения. (Правда, не всякий компилятор сможет её поднять).

Да, кстати. Маячок к неочевидному решению: <stdlib.h>
Перекуём баги на фичи!
Re[2]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 23:38
Оценка:
Я не закрываю глаза на варианты, очень интересно было увидеть различные способы.

Есть вот такой вариант: тоже же через конструктор но без массива,
и даже не знаю есть ли тут рекурсия или цикл (считаю что нет), думаю больше похоже на 'развернутый' массив:
class XXX
{
public:
    XXX(int i, volatile int j=1)
    {
        j /= i;
        cout << "test" << endl;
        XXX a(i-1);
    }
};

int main()
{
    try
    {
        XXX a(4);
    }
    catch (...)
    {
    }
}

Добавлено форматирование — Кодт
Re[4]: Тест на смекалку !
От: Кодт Россия  
Дата: 25.03.06 23:44
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Например, логарифмическая рекурсия в шаблонах — по основанию 2 упомянули, этого достаточно. По основанию 3 или 10 уже будет, во-первых, повтором, а во-вторых, более громоздко.

К>Линейная рекурсия в шаблонах — отдельный класс решения. (Правда, не всякий компилятор сможет её поднять).

Опаньки. Глаза-то у меня замылены... упомянули как раз линейную рекурсию. Для многих компиляторов — это приведёт к ICE. (Насколько помню, только comeau справлялся с глубиной 1000).
Ну раз уж я сам сказал — то приведу это решение.
// с частичной специализацией

template<int N> struct F
{
  void f(const char* s)
  {
    F<N/2>::f(s);
    F<N-N/2>::f(s);
  }
};
template<> struct F<0>
{
  void f(const char* s) { }
};
template<> struct F<1>
{
  void f(const char* s) { cout << s << endl; }
};

int main() { F<1000>::f("hello"); }

// без частичной специализации

template<int N> struct int2type {};

template<int N> void f(const char* s, int2type<N> t)
{
  f(s,int2type<N/2>());
  f(s,int2type<N-N/2>());
}
void f(const char* s, int2type<0> t) {}
void f(const char* s, int2type<1> t) { cout << s << endl; }

int main() { f("hello",int2type<1000>()); }

Дихотомия (N/2, N-N/2) порождает много разных воплощений (instantiations), что утяжеляет работу компилятору.
Самый худший случай — когда N=2^k-1.
Здесь же будут пройдены значения f<N>, N=1000, 500, 250, 125, 63, 62, 32, 31, 16, 15, 8, 7, 4, 3, 2, 1, 0.

Более эффективно — так:
void f(const char* s, int2type<0> t) {}
void f(const char* s, int2type<1> t) { cout << s << endl; }

template<int N> void g(const char* s, int2type<N> t)
{
  f(s, int2type<N%2>());
  g(s, int2type<N/2>());
  g(s, int2type<N/2>());
}
void g(const char* s, int2type<0> t) {}

Будут воплощены g<N>, N = 1000, 500, 250, 125, 62, 31, 15, 7, 3, 1, 0.
Перекуём баги на фичи!
Re[3]: Тест на смекалку !
От: 8bit  
Дата: 25.03.06 23:47
Оценка:
Здравствуйте, 8bit, Вы писали:

8>Я не закрываю глаза на варианты, очень интересно было увидеть различные способы.


8>Есть вот такой вариант: тоже же через конструктор но без массива,

8>и даже не знаю есть ли тут рекурсия или цикл (считаю что нет), думаю больше похоже на 'развернутый' массив:

8>class XXX

8>{
8>public:
8> XXX(int i, volatile int j=1)
8> {
8> j /= i;
8> cout << "test" << endl;
8> XXX a(i-1);
8> }
8>};

8>int main()

8>{
8> try
8> {
8> XXX a(4);
8> }
8> catch (...)
8> {
8> }
8>}

Хотя конечно компилятор развернет это в рекурсию...
Re[3]: Тест на смекалку !
От: Кодт Россия  
Дата: 25.03.06 23:57
Оценка:
Здравствуйте, 8bit, Вы писали:

8>Есть вот такой вариант: тоже же через конструктор но без массива,

8>и даже не знаю есть ли тут рекурсия или цикл (считаю что нет), думаю больше похоже на 'развернутый' массив:

Массива здесь нет, зато есть UB. В конструкторе (считай, в особой функции) создаётся локальная переменная, у которой вызывается конструктор... То есть, эти переменные — во-первых, недостроенные, а во-вторых, не образуют сплошной массив.
Процесс останавливается при делении на ноль (то самое UB).

Даже если при этом возбудится аппаратное исключение — не факт, что будет брошено асинхронное исключение С++. Это личное дело железа, ОС, компилятора, его настроек и твоих рук (иногда нужно явно регистрировать обработчик исключительных ситуаций).
Но пусть произойдёт бросок. Это приведёт к раскрутке стека, т.е., попросту, к возвратам изо всех функций.

То же самое, но более просто
// так
XXX::XXX(int N)
{
  if(N==0) throw int(0); // любой тип исключения, т.к. у нас универсальная ловушка
  cout << "hello\n";
}
// или так
XXX::XXX(int N)
{
  if(N==0) return;
  XXX x(N-1);
}
// или вот так
void f(int N)
{
  if(N==0) return;
  cout << "hello\n";
  f(N-1);
}

То есть, это рекурсия.
Перекуём баги на фичи!
Re[4]: Тест на смекалку !
От: 8bit  
Дата: 26.03.06 01:09
Оценка:
Здравствуйте, Кодт, Вы писали:

Да, кстати. Маячок к неочевидному решению: <stdlib.h>

Это случайно не используя qsort или bsearch ?
Re[4]: Тест на смекалку !
От: 8bit  
Дата: 26.03.06 01:32
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, 8bit, Вы писали:


8>>Есть вот такой вариант: тоже же через конструктор но без массива,

8>>и даже не знаю есть ли тут рекурсия или цикл (считаю что нет), думаю больше похоже на 'развернутый' массив:

К>Массива здесь нет, зато есть UB. В конструкторе (считай, в особой функции) создаётся локальная переменная, у которой вызывается конструктор... То есть, эти переменные — во-первых, недостроенные, а во-вторых, не образуют сплошной массив.

К>Процесс останавливается при делении на ноль (то самое UB).

К>Даже если при этом возбудится аппаратное исключение — не факт, что будет брошено асинхронное исключение С++. Это личное дело железа, ОС, компилятора, его настроек и твоих рук (иногда нужно явно регистрировать обработчик исключительных ситуаций).

К>Но пусть произойдёт бросок. Это приведёт к раскрутке стека, т.е., попросту, к возвратам изо всех функций.

К>То же самое, но более просто

К>
К>// так
К>XXX::XXX(int N)
К>{
К>  if(N==0) throw int(0); // любой тип исключения, т.к. у нас универсальная ловушка
К>  cout << "hello\n";
К>}
К>// или так
К>XXX::XXX(int N)
К>{
К>  if(N==0) return;
К>  XXX x(N-1);
К>}
К>// или вот так
К>void f(int N)
К>{
К>  if(N==0) return;
К>  cout << "hello\n";
К>  f(N-1);
К>}
К>

К>То есть, это рекурсия.

я хотел избежать If.
Сначала именно так и написал, а потом решил через деление на ноль выйти,
раз уж мы хотим посмотреть все возможные варианты.
(так как через исключение никто не предлагал)

Но я думаю элегантнее кода нет... чем тот что был заявлен
Re: Тест на смекалку !
От: ZayatsZ Россия  
Дата: 27.03.06 06:22
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Как вывести строку текста 1000 раз не используя явного или не явного цикла ?



здесь
Автор: kosfr
Дата: 19.01.05

здесь
Автор: PVitaliy
Дата: 18.02.05
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.