Impressão de 1 a 1000 sem loop ou condicionais

323

Tarefa : Imprima números de 1 a 1000 sem usar nenhum loop ou instruções condicionais. Não basta escrever a declaração printf()ou cout1000 vezes.

Como você faria isso usando C ou C ++?

desconhecidos
fonte
137
A resposta óbvia é usar 500 chamadas printfe imprimir dois números de cada vez, não?
James McNellis
433
printf ("números de 1 a 1000");
jondavidjohn
7
:?não é uma declaração condicional (é uma expressão) ...
Chris Lutz
127
A entrevista é sua chance de brilhar. Diga a eles "Sem loops ou condicionais? Brincadeira de criança. Eu posso fazer isso sem um computador!" Em seguida, retire a caneta e o bloco de notas. Eles podem parecer confusos, mas apenas explique que, se você não pode contar com construções de linguagem incorporadas, não pode assumir nada.
JohnFx
8
Pessoalmente, acho que havia várias respostas que tinham soluções inteligentes e interessantes. Eu também acho que, embora essa possa ser facilmente uma péssima pergunta para uma entrevista, poderia ter um bom valor, desde que o entrevistador realmente não busque tanto uma solução completamente bem formada quanto se o entrevistado considerou abordagens que indiquem conhecimento de TMP ou uso de construções de maneiras incomuns. Eu acho que seria ruim se isso fosse usado como uma pergunta pura 'entendi certo / errado', mas se fosse usado como ponto de partida de uma discussão, eu poderia ver muito valor.
Michael Burr

Respostas:

785

Recursão em tempo de compilação! : P

#include <iostream>
template<int N>
struct NumberGeneration{
  static void out(std::ostream& os)
  {
    NumberGeneration<N-1>::out(os);
    os << N << std::endl;
  }
};
template<>
struct NumberGeneration<1>{
  static void out(std::ostream& os)
  {
    os << 1 << std::endl;
  }
};
int main(){
   NumberGeneration<1000>::out(std::cout);
}
Prasoon Saurav
fonte
8
Alguém pode me explicar como isso funciona? bastante impressionante.
Gate
28
@Zack: Vamos ser realistas, estamos imprimindo 1.000 linhas de um programa escrito para evitar deliberadamente loops. O desempenho não é um problema.
dreamlax
42
Para aqueles curiosos o suficiente para compilar isso: em g ++, defina -ftemplate-depth-1000. O máximo de recursão do modelo padrão é 500.
Tom
6
Isso ainda usa condicionais: a correspondência de padrões é glorificada se.
David K.
10
@dreamlax: É apenas uma daquelas coisas que aprendi com a experiência ao longo dos anos: use a '\n'menos que queira realmente liberar, use a ++imenos que você realmente precise do valor anterior i, passe por constreferência, a menos que você tenha um bom motivo para não ... Quando os desenvolvedores param de pensar neles (ou nunca começam), eles, mais cedo ou mais tarde, enfrentam um problema onde isso importa, mas eles nem sabiam que havia pontos em que isso poderia importar.
Sbi
1195

Na verdade, este compila um assembly que não possui condicionais:

#include <stdio.h>
#include <stdlib.h>

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}


Edit: Added '&', por isso considerará o endereço evitando os erros do ponteiro.

Esta versão do anterior no padrão C, uma vez que não depende da aritmética dos ponteiros de função:

#include <stdio.h>
#include <stdlib.h>

void f(int j)
{
    static void (*const ft[2])(int) = { f, exit };

    printf("%d\n", j);
    ft[j/1000](j + 1);
}

int main(int argc, char *argv[])
{
    f(1);
}
Bill
fonte
17
Bem, o código nesta resposta obviamente não é nem C nem C ++, então isso é bom apenas se descartarmos o requisito. Qualquer resposta pode ser qualificada porque um compilador hipotético pode apenas produzir o programa necessário a partir de qualquer entrada.
EQ-
321
@PP, isso é bastante demorado para explicar, mas basicamente jé inicialmente 1porque é realmente argc, ou seja, 1se o programa for chamado sem argumentos. Então, j/1000é 0até jse torna 1000, após o que é 1. (exit - main)é, obviamente, a diferença entre os endereços de exit()e main(). Isso significa que (main + (exit - main)*(j/1000))é main()até jse tornar 1000, após o que se torna exit(). O resultado final main()é chamado quando o programa é iniciado e, em seguida, chama-se recursivamente 999 vezes enquanto incrementa je depois chama exit(). Ufa :)
Frédéric Hamidi
7
Este é um dos abusos mais surpreendentes que a CI já viu. Mas isso funcionará em todas as plataformas?
Qwertie
13
@ Mark: esta é uma assinatura não padrão do main, você não pode chamar o main recursivamente, e o resultado da subtração de ponteiros de função é indefinido.
Yakov Galka
9
Sim, sim, não é um código C ++ estritamente legal pelas razões que @ybungalobill fornece, mas eu tenho que marcar com +1 por pura insanidade e pelo fato de compilar e trabalhar em algumas plataformas. Há momentos em que a resposta correta para "Mas não é padrão!" é "Quem se importa!" :)
j_random_hacker 26/01
544
#include <stdio.h>
int i = 0;
p()    { printf("%d\n", ++i); }
a()    { p();p();p();p();p(); }
b()    { a();a();a();a();a(); }
c()    { b();b();b();b();b(); }
main() { c();c();c();c();c();c();c();c(); return 0; }

Estou surpreso que ninguém parece ter postado isso - eu pensei que era a maneira mais óbvia. 1000 = 5*5*5*8.

Darius Bacon
fonte
As pessoas postaram isso. As outras versões passam o número para imprimir em vez de usar um global, mas é essencialmente a mesma solução.
Chris Lutz
1
@ Chris, eles usam a mesma lógica expressa em macros ou modelos, ampliando o tamanho do código, certo? Você também pode gerar a própria sequência de saída em vez de mil printfs.
Darius Bacon
Ah, sim, vejo que a resposta de Keith gera toda a sequência, legal. :) Eu senti falta disso.
Darius Bacon
43
Bem, bom esforço, mas um pouco estranho que você não se decompôs 8 em 2 * 2 * 2 e, portanto, usar o factorisation nobre única
David Heffernan
298

Parece que não precisa usar loops

printf("1 10 11 100 101 110 111 1000\n");
Johannes Schaub - litb
fonte
1
pode-se argumentar que o uso copyé batota
John Dibling
13
@Johannes, na verdade, tenho certeza que printftem um loop: p
icecrime
1
@litb: Note que eu não disse que "usar copy é trapacear"
John Dibling
2
@ John: copiar é trapaça. você duvida? : P
Nawaz 02/01
1
em uma escala de 1 a 10, qual a chance de eu estar usando binário?
Jordânia
270

Aqui estão três soluções que eu conheço. O segundo pode ser discutido.

// compile time recursion
template<int N> void f1()
{ 
    f1<N-1>(); 
    cout << N << '\n'; 
}

template<> void f1<1>() 
{ 
    cout << 1 << '\n'; 
}

// short circuiting (not a conditional statement)
void f2(int N)
{ 
    N && (f2(N-1), cout << N << '\n');
}

// constructors!
struct A {
    A() {
        static int N = 1;
        cout << N++ << '\n';
    }
};

int main()
{
    f1<1000>();
    f2(1000);
    delete[] new A[1000]; // (3)
    A data[1000]; // (4) added by Martin York
}

[ Edit: (1) e (4) pode ser usado apenas para constantes de tempo de compilação, (2) e (3) também podem ser usados ​​para expressões em tempo de execução - edição final. ]

ybungalobill
fonte
5
Além disso, eu argumentaria que um curto-circuito não é condicional ... Não é uma afirmação, é verdade, mas uma expressão condicional, eu diria. Desde que definamos uma expressão condicional como "algo que produz saltos condicionais no assembler".
Kos
5
Pergunta que me ocorreu ao ler o construtor: O padrão exige que cada item na matriz seja construído em sequência? Seria importante se o construtor tivesse efeitos colaterais. Eu tenho certeza que cada sãs implementos compilador-lo como um loop 0-> 1000, mas gostaria de saber se você poderia ainda estar em conformidade e para trás laço ...
Joseph Garvin
6
@ Joseph - O construtor não deve ser afetado pela ordem em que os objetos individuais são iniciados, mas é uma boa pergunta.
Chris Lutz
12
@ Joseph, isso é definido por 12.6 / 3 (C ++ 03). A inicialização é feita em ordem de assinatura.
Johannes Schaub - litb
2
@Joseph: E eles estão destruídos na ordem inversa também, então você poderia usar um destruidor tão facilmente :)
j_random_hacker
263

Não estou escrevendo a declaração printf 1000 vezes!

printf("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59\n60\n61\n62\n63\n64\n65\n66\n67\n68\n69\n70\n71\n72\n73\n74\n75\n76\n77\n78\n79\n80\n81\n82\n83\n84\n85\n86\n87\n88\n89\n90\n91\n92\n93\n94\n95\n96\n97\n98\n99\n100\n101\n102\n103\n104\n105\n106\n107\n108\n109\n110\n111\n112\n113\n114\n115\n116\n117\n118\n119\n120\n121\n122\n123\n124\n125\n126\n127\n128\n129\n130\n131\n132\n133\n134\n135\n136\n137\n138\n139\n140\n141\n142\n143\n144\n145\n146\n147\n148\n149\n150\n151\n152\n153\n154\n155\n156\n157\n158\n159\n160\n161\n162\n163\n164\n165\n166\n167\n168\n169\n170\n171\n172\n173\n174\n175\n176\n177\n178\n179\n180\n181\n182\n183\n184\n185\n186\n187\n188\n189\n190\n191\n192\n193\n194\n195\n196\n197\n198\n199\n200\n201\n202\n203\n204\n205\n206\n207\n208\n209\n210\n211\n212\n213\n214\n215\n216\n217\n218\n219\n220\n221\n222\n223\n224\n225\n226\n227\n228\n229\n230\n231\n232\n233\n234\n235\n236\n237\n238\n239\n240\n241\n242\n243\n244\n245\n246\n247\n248\n249\n250\n251\n252\n253\n254\n255\n256\n257\n258\n259\n260\n261\n262\n263\n264\n265\n266\n267\n268\n269\n270\n271\n272\n273\n274\n275\n276\n277\n278\n279\n280\n281\n282\n283\n284\n285\n286\n287\n288\n289\n290\n291\n292\n293\n294\n295\n296\n297\n298\n299\n300\n301\n302\n303\n304\n305\n306\n307\n308\n309\n310\n311\n312\n313\n314\n315\n316\n317\n318\n319\n320\n321\n322\n323\n324\n325\n326\n327\n328\n329\n330\n331\n332\n333\n334\n335\n336\n337\n338\n339\n340\n341\n342\n343\n344\n345\n346\n347\n348\n349\n350\n351\n352\n353\n354\n355\n356\n357\n358\n359\n360\n361\n362\n363\n364\n365\n366\n367\n368\n369\n370\n371\n372\n373\n374\n375\n376\n377\n378\n379\n380\n381\n382\n383\n384\n385\n386\n387\n388\n389\n390\n391\n392\n393\n394\n395\n396\n397\n398\n399\n400\n401\n402\n403\n404\n405\n406\n407\n408\n409\n410\n411\n412\n413\n414\n415\n416\n417\n418\n419\n420\n421\n422\n423\n424\n425\n426\n427\n428\n429\n430\n431\n432\n433\n434\n435\n436\n437\n438\n439\n440\n441\n442\n443\n444\n445\n446\n447\n448\n449\n450\n451\n452\n453\n454\n455\n456\n457\n458\n459\n460\n461\n462\n463\n464\n465\n466\n467\n468\n469\n470\n471\n472\n473\n474\n475\n476\n477\n478\n479\n480\n481\n482\n483\n484\n485\n486\n487\n488\n489\n490\n491\n492\n493\n494\n495\n496\n497\n498\n499\n500\n501\n502\n503\n504\n505\n506\n507\n508\n509\n510\n511\n512\n513\n514\n515\n516\n517\n518\n519\n520\n521\n522\n523\n524\n525\n526\n527\n528\n529\n530\n531\n532\n533\n534\n535\n536\n537\n538\n539\n540\n541\n542\n543\n544\n545\n546\n547\n548\n549\n550\n551\n552\n553\n554\n555\n556\n557\n558\n559\n560\n561\n562\n563\n564\n565\n566\n567\n568\n569\n570\n571\n572\n573\n574\n575\n576\n577\n578\n579\n580\n581\n582\n583\n584\n585\n586\n587\n588\n589\n590\n591\n592\n593\n594\n595\n596\n597\n598\n599\n600\n601\n602\n603\n604\n605\n606\n607\n608\n609\n610\n611\n612\n613\n614\n615\n616\n617\n618\n619\n620\n621\n622\n623\n624\n625\n626\n627\n628\n629\n630\n631\n632\n633\n634\n635\n636\n637\n638\n639\n640\n641\n642\n643\n644\n645\n646\n647\n648\n649\n650\n651\n652\n653\n654\n655\n656\n657\n658\n659\n660\n661\n662\n663\n664\n665\n666\n667\n668\n669\n670\n671\n672\n673\n674\n675\n676\n677\n678\n679\n680\n681\n682\n683\n684\n685\n686\n687\n688\n689\n690\n691\n692\n693\n694\n695\n696\n697\n698\n699\n700\n701\n702\n703\n704\n705\n706\n707\n708\n709\n710\n711\n712\n713\n714\n715\n716\n717\n718\n719\n720\n721\n722\n723\n724\n725\n726\n727\n728\n729\n730\n731\n732\n733\n734\n735\n736\n737\n738\n739\n740\n741\n742\n743\n744\n745\n746\n747\n748\n749\n750\n751\n752\n753\n754\n755\n756\n757\n758\n759\n760\n761\n762\n763\n764\n765\n766\n767\n768\n769\n770\n771\n772\n773\n774\n775\n776\n777\n778\n779\n780\n781\n782\n783\n784\n785\n786\n787\n788\n789\n790\n791\n792\n793\n794\n795\n796\n797\n798\n799\n800\n801\n802\n803\n804\n805\n806\n807\n808\n809\n810\n811\n812\n813\n814\n815\n816\n817\n818\n819\n820\n821\n822\n823\n824\n825\n826\n827\n828\n829\n830\n831\n832\n833\n834\n835\n836\n837\n838\n839\n840\n841\n842\n843\n844\n845\n846\n847\n848\n849\n850\n851\n852\n853\n854\n855\n856\n857\n858\n859\n860\n861\n862\n863\n864\n865\n866\n867\n868\n869\n870\n871\n872\n873\n874\n875\n876\n877\n878\n879\n880\n881\n882\n883\n884\n885\n886\n887\n888\n889\n890\n891\n892\n893\n894\n895\n896\n897\n898\n899\n900\n901\n902\n903\n904\n905\n906\n907\n908\n909\n910\n911\n912\n913\n914\n915\n916\n917\n918\n919\n920\n921\n922\n923\n924\n925\n926\n927\n928\n929\n930\n931\n932\n933\n934\n935\n936\n937\n938\n939\n940\n941\n942\n943\n944\n945\n946\n947\n948\n949\n950\n951\n952\n953\n954\n955\n956\n957\n958\n959\n960\n961\n962\n963\n964\n965\n966\n967\n968\n969\n970\n971\n972\n973\n974\n975\n976\n977\n978\n979\n980\n981\n982\n983\n984\n985\n986\n987\n988\n989\n990\n991\n992\n993\n994\n995\n996\n997\n998\n999\n1000\n");

De nada ;)

Martin Thurau
fonte
223
Espero que você tenha escrito um programa para gerar essa linha.
Martin York
32
open ("1000.c", 'w'). write ('printf ("% s");'% ("\ n" .join ([str (x) para x em xrange (1.100)])) ))
Tyler Eaves
53
Espero que o programa que você escreveu para gerar essa linha não contenha loop!
Jeeyoung Kim
20
Uma macro do Vim faria o trabalho rapidamente.
StackedCrooked
2
Um pouco de Perl gera-lo em uma maneira extravagante:$r='printf("'; for (1..1000) { $r.="$_\\n" } $r.='");'; print $r;
sidyll
213
printf("%d\n", 2);
printf("%d\n", 3);

Não imprime todos os números, mas "Imprime números de 1 a 1000". Pergunta ambígua para a vitória! :)

Matthew Flaschen
fonte
77
meu favorito depois de 'printf ("números de 1 a 1000")' - perguntas tolas exigem respostas tolas.
SEngstrom
isso é incrível. +1 para tirar proveito da ambiguidade na pergunta. haha
Nawaz 02/01
2
Editado; de nenhuma maneira, forma ou formulário fez este código print "Print numbers from 1 to 1000."- questão ambígua para a vitória, descrições imprecisas chupar :)
sehe
Uau, ultimamente tem havido um pouco de vandalismo nas respostas desta pergunta. Algo me diz que devemos atualizar esse bloqueio para um histórico.
BoltClock
172

Acione um erro fatal! Aqui está o arquivo countup.c:

#include <stdio.h>
#define MAX 1000
int boom;
int foo(n) {
    boom = 1 / (MAX-n+1);
    printf("%d\n", n);
    foo(n+1);
}
int main() {
    foo(1);
}

Compile e execute em um prompt de shell:

$ ./countup
1
2
3
...
996
997
998
999
1000
Floating point exception
$

Isso de fato imprime os números de 1 a 1000, sem loops ou condicionais!

Aaron Maxwell
fonte
43
você deve chamar fflush (stdout); após cada printf () ... Quando um programa falha, não é garantido que o buffer de saída seja impresso na tela.
Zakk
10
@zakk: Isso não é estritamente necessário - por padrão, o stdout é buffer de linha, portanto \nserá suficiente para liberar a saída.
Psmears
24
stdout é buffer de linha se puder ser determinado como um dispositivo interativo , caso contrário, é totalmente bufferizado. Se o professor redirecionar o stdout para um arquivo para verificação automatizada, você irá falhar :-) #
385
perigo de stackoverflow (por exemplo, num ambiente incorporado)
Hernán Eche
166

Usando comandos do sistema:

system("/usr/bin/seq 1000");
marcog
fonte
15
Alta chance /usr/bin/sequsa um loop internamente. :)
@jokester: você quer dizer, porque o Solaris / BSD não possui um sequtilitário (na configuração padrão)? <grin />
sehe 26/10
Eu odeio dizer isso (bem, não, não sei), mas há um erro na sua solução. Não imprime o conjunto certo de números. :) Aqui está a correção: system("/bin/echo {1..1000}"); se você tivesse escrito o teste de unidade primeiro ...
Don Branson
1
Um cara brilhante decidiu mudar minha resposta, então esse não é o meu erro.
moinudin
100

Não testado, mas deve ser o padrão C de baunilha:

void yesprint(int i);
void noprint(int i);

typedef void(*fnPtr)(int);
fnPtr dispatch[] = { noprint, yesprint };

void yesprint(int i) {
    printf("%d\n", i);
    dispatch[i < 1000](i + 1);
}

void noprint(int i) { /* do nothing. */ }

int main() {
    yesprint(1);
}
maravilhoso
fonte
29
@ Pasoon: É uma relação.
Yakov Galka
28
o requisito é "sem condicionais" (if, switch, etc). não "sem condições"
jon_darkstar 31/12/10
32
<não é uma condição. É um operador relacional. if/ elseé uma declaração condicional. ?:é um operador condicional. <é apenas um operador que retorna um valor booleano. Provavelmente é uma instrução de máquina única, sem saltos ou qualquer coisa.
Chris Lutz
12
@ Chris Lutz: Em x86, é 3 Instruções: cmpl, setle, e movzbl. x86-64 é isso mais um cltq. PowerPC é de 2 instruções: cmpwie crnot.
Adam Rosenfield
4
1 - i / 1000. Sem comparações!
Thai
96

Um pouco chato em comparação com os outros aqui, mas provavelmente o que eles estão procurando.

#include <stdio.h>

int f(int val) {
    --val && f(val);
    return printf( "%d\n", val+1);
}

void main(void) {
    f(1000);
}
Aaron
fonte
Tornou mais curto. defina i = 1 fora do main e depois dentro do main: printf ("% d \ n", 11 - i) && --i && main (i);
jftuga
3
@ Jens Schauder: Aproveitando a &&avaliação preguiçosa na primeira linha de f().
Rafał Dowgird
10
Isso não é chato, é simples. Se você pode fazer a mesma coisa com uma pequena função que você puder com uma grande confusão de magia modelo, então você deve fazê-lo com a função :)
amertune
21
O && é uma condição. Um AND matemático avaliará os dois lados (como o Java & e o Ada "AND" faz). && avaliará o segundo operador apenas se (aqui está) o primeiro for verdadeiro. Ou outro exemplo: em Ada, o operador de curto-circuito é chamado "OR THEN" - usando THEN para indicar o aspecto condicional. Desculpe, você poderia ter usado tão bem o? : operador.
Martin
Não precisa se desculpar. && é um operador de comparação. O operador ternário é uma condicional.
Aaron
71

A tarefa nunca especificou que o programa deve terminar após 1000.

void f(int n){
   printf("%d\n",n);
   f(n+1);
}

int main(){
   f(1);
}

( Pode ser reduzido para isso se você executar ./a.out sem parâmetros adicionais )

void main(int n) {
   printf("%d\n", n);
   main(n+1);
}
Brian
fonte
Porém, ele não para em 1000. Apenas continua.
Remy Lebeau
Só pode ser reduzido se você eliminar o requisito de C ou C ++. Então qualquer "programa" funcionará, porque um compilador teórico pode gerar o programa que você deseja (a partir de qualquer entrada).
EQ-
@eq Novamente, isso compila e roda muito bem ...
Mark McDonald
72
Como uma reflexão tardia: podemos até fugir da matemática aparente . Se empregarmos rand(), imprimiremos todos os números de 1 a 1000. Eventualmente =: P
5
@pooh: Não necessariamente, já que rand () tem a chance de repetir após determinada seqüência, e que a seqüência pode ser não cair no conjunto solução para este problema
dchhetri
71

Fácil como torta! : P

#include <iostream>

static int current = 1;

struct print
{
    print() { std::cout << current++ << std::endl; }
};

int main()
{
    print numbers [1000];
}
Zelix
fonte
você pode querer fazer "int estática atual = 0" caso contrário irá imprimir a partir de 2 a 1001.
Shinnok
i mudou atual ++ a atual ++
Zelix
65
#include <stdio.h>
#define Out(i)       printf("%d\n", i++);
#define REP(N)       N N N N N N N N N N
#define Out1000(i)   REP(REP(REP(Out(i))));
void main()
{
 int i = 1;
 Out1000(i);
}
MangleSky
fonte
3
Ummmm. Macros. É para o jantar.
EvilTeach
42

Podemos lançar 1000 linhas, cada uma imprimindo um dos números. Instale o OpenMPI , compile usando mpicxx -o 1000 1000.cppe execute usando mpirun -np 1000 ./1000. Você provavelmente precisará aumentar seu limite de descritor usando limitou ulimit. Observe que isso será bastante lento, a menos que você tenha muitos núcleos!

#include <cstdio>
#include <mpi.h>
using namespace std;

int main(int argc, char **argv) {
  MPI::Init(argc, argv);
  cout << MPI::COMM_WORLD.Get_rank() + 1 << endl;
  MPI::Finalize();
}

Obviamente, os números não serão necessariamente impressos em ordem, mas a pergunta não exige que eles sejam solicitados.

moinudin
fonte
1
Loop implícito na biblioteca? Mas +1 de qualquer maneira para uma nova abordagem.
Chris Lutz
11
@ Chris Não a maioria das soluções tem um loop oculto em algum lugar?
moinudin
Suponho que, se você adotar a abordagem "loops no compilador". Como (fora de um possível loop sobre os argumentos em MPI::Init()) não consigo imaginar loops no binário real do seu programa 1000.cpp, dei um +1, mesmo que certamente haja loops em execução quando você o executa.
Chris Lutz
40

Com C simples:

#include<stdio.h>

/* prints number  i */ 
void print1(int i) {
    printf("%d\n",i);
}

/* prints 10 numbers starting from i */ 
void print10(int i) {
    print1(i);
    print1(i+1);
    print1(i+2);
    print1(i+3);
    print1(i+4);
    print1(i+5);
    print1(i+6);
    print1(i+7);
    print1(i+8);
    print1(i+9);
}

/* prints 100 numbers starting from i */ 
void print100(int i) {
    print10(i);
    print10(i+10);
    print10(i+20);
    print10(i+30);
    print10(i+40);
    print10(i+50);
    print10(i+60);
    print10(i+70);
    print10(i+80);
    print10(i+90);
}

/* prints 1000 numbers starting from i */ 
void print1000(int i) {
    print100(i);
    print100(i+100);
    print100(i+200);
    print100(i+300);
    print100(i+400);
    print100(i+500);
    print100(i+600);
    print100(i+700);
    print100(i+800);
    print100(i+900);
}


int main() {
        print1000(1);
        return 0;
}

Obviamente, você pode implementar a mesma idéia para outras bases (2: print2 print4 print8 ...), mas o número 1000 aqui sugeriu a base 10. Você também pode reduzir um pouco o número de linhas adicionando funções intermediárias: print2() print10() print20() print100() print200() print1000()e outras alternativas equivalentes.

leonbloy
fonte
Por que o número 1000 sugere a base 10? Em qualquer notação posicional com base B, 1000 é um número perfeitamente válido e sempre é igual B^3.
Philip
Eu apenas quis dizer que, considerando como o número é representado na base 10, a fatoração "10x10x10" se sugeria, mas que outras alternativas são possíveis. Eu acho que eu deveria ter dito "fatoração" em vez de "base"
leonbloy
34

Basta usar std :: copy () com um iterador especial.

#include <algorithm>
#include <iostream>
#include <iterator>

struct number_iterator
{
    typedef std::input_iterator_tag iterator_category;
    typedef int                     value_type;
    typedef std::size_t             difference_type;
    typedef int*                    pointer;
    typedef int&                    reference;

    number_iterator(int v): value(v)                {}
    bool operator != (number_iterator const& rhs)   { return value != rhs.value;}
    number_iterator operator++()                    { ++value; return *this;}
    int operator*()                                 { return value; }
    int value;
};



int main()
{
    std::copy(number_iterator(1), 
              number_iterator(1001), 
              std::ostream_iterator<int>(std::cout, " "));
}
Loki Astari
fonte
Eu acho que seu código começa em 0. Também concordo com Chris, a pergunta como a vi anos atrás foi declarada como "sem nenhuma biblioteca, exceto IO". ainda +1 :)
Yakov Galka
3
@ Chris Lutz: A implementação da cópia é indefinida. Eu posso até usar o código do modelo como acima (você simplesmente não sabe). Então você não pode dizer que usa um loop porque não sabemos.
Martin York
7
Na verdade, minha nit pick não seria o loop implícito std::copytanto quanto o condicional implícito no operator !=(). Independentemente disso, é uma visão inteligente do processamento de um intervalo, e abordagens inteligentes é o que eu procuro em resposta a perguntas como essa.
Michael Burr
implementação específica é indefinida
selvaiyyamperumal 28/11/11
@selvaiyyamperumal: Não sei exatamente do que você está falando. Mas se você está falando sobre comportamento, o padrão não concorda com você. "Comportamento definido pela implementação" significa que está bem definido, mas deve ser explicitamente documentado pela implementação. "Comportamento indefinido" significa que tudo pode acontecer.
Martin York
33

Função ponteiro (ab) uso. Nenhuma mágica do pré-processador para aumentar a saída. ANSI C.

#include <stdio.h>

int i=1;

void x10( void (*f)() ){
    f(); f(); f(); f(); f();
    f(); f(); f(); f(); f();
}

void I(){printf("%i ", i++);}
void D(){ x10( I ); }
void C(){ x10( D ); }
void M(){ x10( C ); }

int main(){
    M();
}
Filipe Z
fonte
3
Era nisso que eu estava pensando. Uma pessoa anterior disse que 5 * 5 * 5 * 8 = 1000. Eu pensei que era engraçado ele sentir falta dos 10 ^ 3 óbvios. Ótima solução!
Evan Moran
32
#include <iostream>
#include <iterator>
using namespace std;

int num() { static int i = 1; return i++; }
int main() { generate_n(ostream_iterator<int>(cout, "\n"), 1000, num); }
Dustin
fonte
30

Resposta C feia (desenrolada para apenas um quadro de pilha por potência de 10):

#define f5(i) f(i);f(i+j);f(i+j*2);f(i+j*3);f(i+j*4)
void f10(void(*f)(int), int i, int j){f5(i);f5(i+j*5);}
void p1(int i){printf("%d,",i);}
#define px(x) void p##x##0(int i){f10(p##x, i, x);}
px(1); px(10); px(100);

void main()
{
  p1000(1);
}
Martin
fonte
3
tudo bem, mas por que "void main ()"? maus hábitos raramente vão? : P
Nawaz 02/01
30
@Nawaz: Como esse é um aplicativo da GUI do Windows, não importa. Só chamei de "principal" porque estava pensando em lagostas e com uma ortografia terrível.
Martin
29

Estouro de pilha:

#include <stdio.h>

static void print_line(int i)
{   
 printf("%d\n", i); 
 print_line(i+1);
}   

int main(int argc, char* argv[])
{   
 //get up near the stack limit
 char tmp[ 8388608 - 32 * 1000 - 196 * 32 ];
 print_line(1);
} 

Isto é para uma pilha de 8 MB. Cada chamada de função parece levar cerca de 32 bytes (daí o 32 * 1000). Mas quando eu o executei, cheguei a 804 (daí o 196 * 32; talvez o tempo de execução C tenha outras partes na pilha que você deve deduzir também).

user560766
fonte
25

Diversão com ponteiros de função (não é necessário nada disso TMP novo):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>


#define MSB(typ) ((sizeof(typ) * CHAR_BIT) - 1)

void done(int x, int y);
void display(int x, int y);

void (*funcs[])(int,int)  = {
    done,
    display
};

void done(int x, int y)
{
    exit(0);
}

void display(int x, int limit)
{
    printf( "%d\n", x);
    funcs[(((unsigned int)(x-limit)) >> MSB(int)) & 1](x+1, limit);
}


int main()
{
    display(1, 1000);
    return 0;
}

Como observação lateral: tomei a proibição contra condicionais para estender também aos operadores lógicos e relacionais. Se você permitir negação lógica, a chamada recursiva poderá ser simplificada para:

funcs[!!(limit-1)](x+1, limit-1);
Michael Burr
fonte
Eu gosto do jeito que você consegue com a mudança de bits. mas com sua simplificação tardia, o que o double bang faz? é bit a bit ou lógico? im perdido e google me pegou andando em círculosfuncs[!!(limit-1)](x+1, limit-1);
jon_darkstar
Eu prefiro ter um único !e alternar os elementos da matriz do ponteiro de função, mas não sei se isso funcionará bem com sua outra loucura.
Chris Lutz
@ Chris: Eu concordo completamente - mas não considerei usar operadores lógicos / de relacionamento até depois da publicação e achei que um patch de linha única seria mais apropriado. Além disso, ele se encaixa um pouco melhor com toda a sensação ofuscada do problema.
Michael Burr
24

Eu sinto que esta resposta será muito simples e fácil de entender.

int print1000(int num=1)
{
    printf("%d\n", num);

    // it will check first the num is less than 1000. 
    // If yes then call recursive function to print
    return num<1000 && print1000(++num); 
}

int main()
{
    print1000();
    return 0;        
}
Pappu
fonte
3
Sua resposta usa declarações condicionais, que são proibidas de acordo com a pergunta.
stevelove
4
declarações condicionais são se mais etc. Acabei de usar uma operação lógica !! Hpe está claro!
Pappu
2
Mesmo nos seus comentários, você escreveu "Se sim, chame a função recursiva para imprimir". Uma condicional escrita de maneira não óbvia ainda é condicional. O padrão num também é condicional.
Gerry
23

Perdi toda a diversão, todas as boas respostas C ++ já foram publicadas!

Esta é a coisa mais estranha que eu poderia inventar, mas eu não apostaria que é legal o C99: p

#include <stdio.h>

int i = 1;
int main(int argc, char *argv[printf("%d\n", i++)])
{
  return (i <= 1000) && main(argc, argv);
}

Outro, com um pouco de trapaça:

#include <stdio.h>
#include <boost/preprocessor.hpp>

#define ECHO_COUNT(z, n, unused) n+1
#define FORMAT_STRING(z, n, unused) "%d\n"

int main()
{
    printf(BOOST_PP_REPEAT(1000, FORMAT_STRING, ~), BOOST_PP_ENUM(LOOP_CNT, ECHO_COUNT, ~));
}

Última idéia, mesma fraude:

#include <boost/preprocessor.hpp>
#include <iostream>

int main()
{
#define ECHO_COUNT(z, n, unused) BOOST_PP_STRINGIZE(BOOST_PP_INC(n))"\n"
    std::cout << BOOST_PP_REPEAT(1000, ECHO_COUNT, ~) << std::endl;
}
gelo
fonte
Chamar mainresulta em comportamento indefinido, como me lembro.
Yakov Galka
4
É perfeitamente legal C. @ybungalobill: Você deve pensar em C ++, onde a chamada de main () é especificamente proibida.
Michael Foukarakis
@Michael: Talvez eu não esteja muito familiarizado com C. #
Yakov Galka
Eu acho que usar o Boost implica C ++. Independentemente disso, parabéns pela solução Boost.PP.
ME22
6
Os operadores lógicos &&e ||provavelmente se enquadram em "condicionais", uma vez que curto-circuito (como seria ?:).
112511
22

Fácil como torta:

int main(int argc, char* argv[])
{
    printf(argv[0]);
}

método de execução:

printer.exe "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;91;92;93;94;95;96;97;98;99;100;101;102;103;104;105;106;107;108;109;110;111;112;113;114;115;116;117;118;119;120;121;122;123;124;125;126;127;128;129;130;131;132;133;134;135;136;137;138;139;140;141;142;143;144;145;146;147;148;149;150;151;152;153;154;155;156;157;158;159;160;161;162;163;164;165;166;167;168;169;170;171;172;173;174;175;176;177;178;179;180;181;182;183;184;185;186;187;188;189;190;191;192;193;194;195;196;197;198;199;200;201;202;203;204;205;206;207;208;209;210;211;212;213;214;215;216;217;218;219;220;221;222;223;224;225;226;227;228;229;230;231;232;233;234;235;236;237;238;239;240;241;242;243;244;245;246;247;248;249;250;251;252;253;254;255;256;257;258;259;260;261;262;263;264;265;266;267;268;269;270;271;272;273;274;275;276;277;278;279;280;281;282;283;284;285;286;287;288;289;290;291;292;293;294;295;296;297;298;299;300;301;302;303;304;305;306;307;308;309;310;311;312;313;314;315;316;317;318;319;320;321;322;323;324;325;326;327;328;329;330;331;332;333;334;335;336;337;338;339;340;341;342;343;344;345;346;347;348;349;350;351;352;353;354;355;356;357;358;359;360;361;362;363;364;365;366;367;368;369;370;371;372;373;374;375;376;377;378;379;380;381;382;383;384;385;386;387;388;389;390;391;392;393;394;395;396;397;398;399;400;401;402;403;404;405;406;407;408;409;410;411;412;413;414;415;416;417;418;419;420;421;422;423;424;425;426;427;428;429;430;431;432;433;434;435;436;437;438;439;440;441;442;443;444;445;446;447;448;449;450;451;452;453;454;455;456;457;458;459;460;461;462;463;464;465;466;467;468;469;470;471;472;473;474;475;476;477;478;479;480;481;482;483;484;485;486;487;488;489;490;491;492;493;494;495;496;497;498;499;500;501;502;503;504;505;506;507;508;509;510;511;512;513;514;515;516;517;518;519;520;521;522;523;524;525;526;527;528;529;530;531;532;533;534;535;536;537;538;539;540;541;542;543;544;545;546;547;548;549;550;551;552;553;554;555;556;557;558;559;560;561;562;563;564;565;566;567;568;569;570;571;572;573;574;575;576;577;578;579;580;581;582;583;584;585;586;587;588;589;590;591;592;593;594;595;596;597;598;599;600;601;602;603;604;605;606;607;608;609;610;611;612;613;614;615;616;617;618;619;620;621;622;623;624;625;626;627;628;629;630;631;632;633;634;635;636;637;638;639;640;641;642;643;644;645;646;647;648;649;650;651;652;653;654;655;656;657;658;659;660;661;662;663;664;665;666;667;668;669;670;671;672;673;674;675;676;677;678;679;680;681;682;683;684;685;686;687;688;689;690;691;692;693;694;695;696;697;698;699;700;701;702;703;704;705;706;707;708;709;710;711;712;713;714;715;716;717;718;719;720;721;722;723;724;725;726;727;728;729;730;731;732;733;734;735;736;737;738;739;740;741;742;743;744;745;746;747;748;749;750;751;752;753;754;755;756;757;758;759;760;761;762;763;764;765;766;767;768;769;770;771;772;773;774;775;776;777;778;779;780;781;782;783;784;785;786;787;788;789;790;791;792;793;794;795;796;797;798;799;800;801;802;803;804;805;806;807;808;809;810;811;812;813;814;815;816;817;818;819;820;821;822;823;824;825;826;827;828;829;830;831;832;833;834;835;836;837;838;839;840;841;842;843;844;845;846;847;848;849;850;851;852;853;854;855;856;857;858;859;860;861;862;863;864;865;866;867;868;869;870;871;872;873;874;875;876;877;878;879;880;881;882;883;884;885;886;887;888;889;890;891;892;893;894;895;896;897;898;899;900;901;902;903;904;905;906;907;908;909;910;911;912;913;914;915;916;917;918;919;920;921;922;923;924;925;926;927;928;929;930;931;932;933;934;935;936;937;938;939;940;941;942;943;944;945;946;947;948;949;950;951;952;953;954;955;956;957;958;959;960;961;962;963;964;965;966;967;968;969;970;971;972;973;974;975;976;977;978;979;980;981;982;983;984;985;986;987;988;989;990;991;992;993;994;995;996;997;998;999;1000"

A especificação não diz que a sequência deve ser gerada dentro do código :)

Rodrigo
fonte
18
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;

class Printer
{
public:
 Printer() { cout << ++i_ << "\n"; }
private:
 static unsigned i_;
};

unsigned Printer::i_ = 0;

int main()
{
 Printer p[1000];
}
John Dibling
fonte
15
#include <stdio.h>

void nothing(int);
void next(int);
void (*dispatch[2])(int) = {next, nothing};

void nothing(int x) { }
void next(int x)
{
    printf("%i\n", x);
    dispatch[x/1000](x+1);
}

int main()
{
    next(1);
    return 0;
}
6502
fonte
15

Mais abuso do pré-processador:

#include <stdio.h>

#define A1(x,y) #x #y "0\n" #x #y "1\n" #x #y "2\n" #x #y "3\n" #x #y "4\n" #x #y "5\n" #x #y "6\n" #x #y "7\n" #x #y "8\n" #x #y "9\n"
#define A2(x) A1(x,1) A1(x,2) A1(x,3) A1(x,4) A1(x,5) A1(x,6) A1(x,7) A1(x,8) A1(x,9)
#define A3(x) A1(x,0) A2(x)
#define A4 A3(1) A3(2) A3(3) A3(4) A3(5) A3(6) A3(7) A3(8) A3(9)
#define A5 "1\n2\n3\n4\n5\n6\n7\n8\n9\n" A2() A4 "1000\n"

int main(int argc, char *argv[]) {
    printf(A5);
    return 0;
}

Eu me sinto tão sujo; Eu acho que vou tomar banho agora.

keithmo
fonte
2
Você pode ligar A2()sem um argumento como esse?
Chris Lutz
Eu também estava curioso sobre isso. Funciona corretamente com o GCC, mas não sei se é um comportamento bem definido.
keithmo
Bem definido no C99, não se lembra do que o C89 disse, causa problemas com pelo menos algumas versões do MSVC se a memória servir.
Zwol
15

Se soluções POSIX forem aceitas:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>

static void die(int sig) {
    exit(0);
}

static void wakeup(int sig) {
    static int counter = 1;
    struct itimerval timer;
    float i = 1000 / (1000 - counter);

    printf("%d\n", counter++);

    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 0;
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = i; /* Avoid code elimination */
    setitimer(ITIMER_REAL, &timer, 0);
}

int main() {
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    signal(SIGFPE, die);
    signal(SIGALRM, wakeup);
    wakeup(0);
    pthread_mutex_lock(&mutex);
    pthread_mutex_lock(&mutex); /* Deadlock, YAY! */
    return 0;
}
jweyrich
fonte
13

Como não há restrição para erros ..

int i=1; int main() { int j=i/(i-1001); printf("%d\n", i++); main(); }

Ou ainda melhor (?),

#include <stdlib.h>
#include <signal.h>

int i=1;
int foo() { int j=i/(i-1001); printf("%d\n", i++); foo(); }

int main()
{
        signal(SIGFPE, exit);
        foo();
}
Serkan
fonte
2
Você deve evitar otimizações do compilador para manter o j não utilizado.
bandi
2
Ele só precisa adicionar volatileà declaração dej
Patrick Schlüter