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 ++?


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);
}

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);
}

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.


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");

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. ]


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 ;)


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! :)


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!


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");

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);
}

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);
}

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);
}

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];
}

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);
}

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.


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.


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, " "));
}

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();
}

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); }

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);
}

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).


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);

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;        
}

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;
}

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 :)


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];
}

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;
}

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.


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;
}

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();
}

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.