A cada 2 ^ n vezes


10

Seja no número de vezes que seu programa foi executado. Se nfor uma potência de 2, imprima 2^xonde n = 2^x; caso contrário, basta imprimir o número. Exemplo de execução:

[1st time] 2^0
[2nd time] 2^1
[3rd time] 3
[4th time] 2^2
[5th time] 5

e assim por diante. Este é um concurso de popularidade, por isso ganha a resposta com mais votos positivos.


3
por que ele sai 0na primeira execução?
Mniip

você quis dizer "onde n = 2^xCaso contrário, a segunda vez que a saída seria? 2^4, pela quarta vez 2^16e assim por diante.
John Dvorak

@mniip ambos os erros de digitação. Provavelmente eu deveria ter lido isso com mais cuidado ...: P
Jwosty 4/14

4
Umm ... 1é um poder de dois. 2^0=1
John Dvorak

11
Você ainda dizer x = 2^x, em vez den = 2^x
John Dvorak

Respostas:


8

Java - Abuso de API

Há muitos computadores on-line que podem contar, então, por que armazenar a conta sozinho?

Abuso total da API Stack para obter a cota e a cota restante para ver quantas vezes ela foi executada hoje:

public static void main(String[] args) throws Exception {
    URLConnection c = new URL("http://api.stackexchange.com/2.2/info?site=stackoverflow").openConnection();
    c.setRequestProperty("Accept-Encoding", "gzip");
    GZIPInputStream gz = new GZIPInputStream(c.getInputStream());
    BufferedReader r = new BufferedReader(new InputStreamReader(gz));
    String reply = r.readLine();
    r.close();

    reply = reply.substring(reply.indexOf("quota_max"), reply.length()-1);
    String[] t = reply.split("[:,]");
    int runs = Integer.parseInt(t[1]) - Integer.parseInt(t[3]);        
    if((runs & (runs -1)) == 0){
        int exp = 0;
        while(runs % 2 == 0){
            runs = runs >> 1;
            exp++;
        }
        System.out.println("2^" + exp);
    } else {
        System.out.println("" + runs);
    }
}

Obviamente, isso funciona apenas com uma nova cota diária para o seu IP e apenas até a cota. Se você quiser suporte para números mais altos, postar um [recurso de pedido] para aumentar quota_maxa MAX_INT.


6

Javascript

alert((n=Math.log((l=localStorage).m=~~l.m+1)/Math.log(2))==(n|0)?"2^"+n:l.m)

Os alertas sucessivos são os seguintes:

2^0
2^1
3
2^2
5
6
7
2^3
9
...and so on.

Obrigado gentilmente ... 'Era a única maneira de acompanhar as execuções em JavaScript ... Estou pensando em usar o localStorage para um próximo jogo de JS ... #
413 WallyWest

Para algo tão pequeno quanto um balcão, um cookie também deve funcionar.
Celtschk 6/03/2014

@celtschk Grande ideia, mas acredito que fazendo um cookie teria levado mais bytes
Wally West

6

C - escrevendo no executável

Esse código C atualiza a sequência datano executável, portanto, essencialmente, esse é o código de modificação automática. Se você executá-lo mais de 9.999.999 vezes, obtém coisas interessantes.

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

int main(int argc,char **argv){
    //               'abcdefghijklmnopqrstuvwxyz1' << that's 27 characters inside the quotes
    const char *data="Da best marker in da world 1\0\0\0\0\0\0";
    FILE *f;
    int i,n,m;
    char c;
    long int pos;
    m=n=strtol(data+27,NULL,10);
    i=0;
    while(1){
        if(n==0){
            printf("This code should never have been reached... Unless you've messed with my executable.\n");
            return 1;
        }
        if(n==1){
            printf("2^%d\n",i);
            break;
        }
        if(n&1){
            printf("%d\n",m);
            break;
        }
        i++;
        n>>=1;
    }
    f=fopen(argv[0],"r+b");
    i=0;
    c=fgetc(f);
    while(!feof(f)){
        if(data[i]==c){
            i++;
            if(i==27)break;
        } else i=0;
        c=fgetc(f);
    }
    if(i!=27)return 1;
    n=0;
    pos=ftell(f);
    c=fgetc(f);
    while(c!='\0'){
        n=10*n+c-'0';
        c=fgetc(f);
    }
    n++; //The big increment!
    fseek(f,pos,SEEK_SET);
    fprintf(f,"%d",n);
    fflush(f);
    fclose(f);
    return 0;
}

Ele segmentação falhas depois de compilar com GCC 4.8.1-10ubuntu9: gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla

11
No Mac, ele não testou o Linux ou o Windoze. Aparentemente, o Linux é mais rigoroso com o acesso a si mesmo.
tomsmeding

6

Java

O código a seguir modifica seu próprio arquivo de classe para armazenar a nova contagem de execuções. Isso foi especialmente divertido quando você não tinha idéia da aparência do código de bytes, mas após inúmeras horas pesquisando e pesquisando no Google finalmente funciona! :)

Demo (usando 7 como valor inicial para fins de demonstração):

[timwolla@/data/workspace/java]javac Runs.java 
[timwolla@/data/workspace/java]java Runs 
7
[timwolla@/data/workspace/java]java Runs 
2^3
[timwolla@/data/workspace/java]java Runs 
9
[timwolla@/data/workspace/java]java Runs 
10

Código:

import java.io.*;
import java.util.*;

class Runs {

    public static void main(String[] args) throws Exception {
        // RUN-- makes the string easy to find in the byte code
        String runString = "RUN--1";

        // extract the number
        int runs = Integer.parseInt(runString.substring(5));

        // output the number properly
        int power = 0;
        boolean outputted = false;
        while (Math.pow(2, power) <= runs) {
            if (Math.pow(2, power) == runs) {
                outputted = true;
                System.out.println("2^"+power);
            }
            power++;
        }
        if (!outputted) System.out.println(runs);

        // increase run count
        runs++;

        // build new string
        String newRunString = runString.substring(0, 5) + runs;

        // get folder of class file
        String folder = Runs.class.getProtectionDomain().getCodeSource().getLocation().getFile();
        // append class file name
        String me = folder + "/Runs.class";

        // and open it up
        RandomAccessFile in = new RandomAccessFile(me, "rw");

        int read;
        int state = 0;
        while ((read = in.read()) != -1) {
            char c = (char) read;

            // state machine to find the RUN--
            switch (state) {
                case 0:
                    // 2 bytes before: upper byte of the two byte length
                    if (c == ((runString.length() >> 8) & 0xFF)) state++;
                break;
                case 1:
                    // 1 byte before: lower byte of the two byte length
                    if (c == (runString.length() & 0xFF)) state++;
                    else state = 0;
                break;
                case 2:
                    if (c == 'R') state++;
                    else state = 0;
                break;
                case 3:
                    if (c == 'U') state++;
                    else state = 0;
                break;
                case 4:
                    if (c == 'N') state++;
                    else state = 0;
                break;
                case 5:
                case 6:
                    if (c == '-') state++;
                    else state = 0;
                break;
                case 7:
                    // we found run, now: Modify byte code

                    // back to the bytes that determine the length
                    in.seek(in.getFilePointer() - 8);

                    // expand the file if neccessary
                    int lengthChange = (newRunString.length() - runString.length());
                    in.setLength(in.length() + lengthChange);

                    // write new length
                    in.writeByte(((newRunString.length() >> 8) & 0xFF));
                    in.writeByte((newRunString.length() & 0xFF));

                    // length changed, shift all the following bytes by one
                    if (lengthChange > 0) {
                        long target = in.getFilePointer();
                        in.seek(in.length() - 1 - lengthChange);
                        while (in.getFilePointer() > target) {
                            in.write(in.read());
                            in.seek(in.getFilePointer() - 3);
                        }
                        in.seek(target);
                    }

                    // write new string
                    in.writeBytes(newRunString);

                    return;
                case 8:
            }
        }
    }
}

5

dg

Aqui, apresento um código portátil! A cada corrida, a #é adicionada no final, criando uma barra de progresso! Além disso, você pode mover o código para outra máquina e retomar de onde estava.

import '/math'

with fd = open __file__ 'r' =>
  code = fd.read!
  times = code.count('#') - 2
with fd = open __file__ 'w' =>
  fd.write $ code.rstrip! + '#'
exp = math.log2 times
if exp.is_integer! => print $ '2^{}'.format $ int exp
   otherwise => print times

#

Após 18 vezes:

import '/math'

with fd = open __file__ 'r' =>
  code = fd.read!
  times = code.count('#') - 2
with fd = open __file__ 'w' =>
  fd.write $ code.rstrip! + '#'
exp = math.log2 times
if exp.is_integer! => print $ '2^{}'.format $ int exp
   otherwise => print times

###################

Ahh, obrigado por apontar esse idioma para mim. Ele incorpora o que eu amo tanto em Python quanto em Haskell.
Kaya

@Kaya Estou feliz que você gostou! Caso você ainda não tenha visto, há uma página inicial em pyos.github.io/dg e um tutorial também! Muitas mercadorias. E não hesite em abrir um problema no repositório, se desejar. EDIT: Eu só queria ressaltar que não sou o criador do lang.
Rubik

5

Exemplo de Ruby baseado em Sinatra

Essa solução baseada em servidor armazena um contador pessoal para cada usuário em um cookie.

Experimente em http://every-2-to-the-n-times.herokuapp.com/

require 'sinatra'
require 'sinatra/cookies'

# https://github.com/sinatra/sinatra-contrib/issues/113
set :cookie_options, :domain => nil

get '/' do
   x = cookies[:x].to_i || 1
   cookies[:x] = x + 1

   # power of 2 test from http://grosser.it/2010/03/06/check-if-a-numer-is-a-power-of-2-in-ruby/
   return (x & (x - 1) == 0) ? "2^#{Math.log2(x).to_i}" : x.to_s
end

5

perl

Aqui está um pouco de perl para fazer isso. Onde os dados devem ser armazenados? Por que no próprio arquivo do programa, é claro! =)

$b = sprintf '%b', $x=x();
print $b=~/^10*$/ ? "2^".(length($b)-1) : $x, "\n";
open F, "+<", $0;
seek F, -3-length $x, 2;
print F $x+1, " }\n";
sub x { 1 }

Originalmente, eu havia usado o identificador de arquivo DATA mágico dessa maneira, mas sinto que o acima é "mais puro":

$b = sprintf '%b', $x = <DATA>;
print $b =~ /^10*$/ ? "2^".(length($b)-1)."\n" : $x;
open F, "+<", $0;
seek F, -length $x, 2;
print F $x+1, "\n";
__DATA__
1

Você pode armazenar tell DATAantes de ler e procurar novamente nesse local.
mob

3

Bater

Script shell simples de auto-edição.

n=1;e=0;p=1
sed -i s/"n=$n"/"n=`expr $n + 1`"/g $0
if [[ $n -eq $p ]];then
    echo 2^$e
    sed -i s/"p=$p"/"p=`expr $p \* 2`"/g $0
    sed -i s/"e=$e"/"e=`expr $e + 1`"/g $0
else
    echo $n
fi

2

Bater

I como dfernig 's solução Bash , mas eu gostaria de postar meu também:

n=$(expr `cat $0|wc -c` - 170)
if [ $(echo "obase=2;$n"|bc|grep -o 1|wc -l) == 1 ]
then echo -n "2^"; echo "obase=2;$n"|bc|grep -o 0|wc -l;
else echo $n; fi
echo "" >> $0

Eu acho que a solução pode ser considerada diferente, porque

  • o código realmente executado não muda
  • o programa calcula dinamicamente se n é uma potência de 2

A "memória" é o tamanho do script (inicialmente 171 bytes), que é aumentado em 1 com o acréscimo de uma nova linha a cada execução.
Poderes de 2 são reconhecidos convertendo o tamanho do programa (menos 170, é claro) em binário e depois contando os: se houver exatamente um, então n é uma potência de 2. O expoente é o número de zeros em binário .


1

Solução Java

Usando a API de preferências do java para armazenar a quantidade de execução; e pré-calculou os poderes de 2 para um hashmap comparar

import java.util.HashMap;
import java.util.prefs.Preferences;
class Pow
{
    public static void main(String[]a)
    {
        int rt = Integer.valueOf(Preferences.userRoot().get("Pow.run", "1"));
        HashMap<String,Integer> powof2 = new HashMap<>();
        //pregenerating the powers of 2;
        for (int i = 0; i < 46340; i++)//highest power of 2 before int overflow
        {
            powof2.put(((int)Math.pow(2, i))+"",i);
        }
        if(powof2.containsKey(rt+""))
        {System.out.println("2^"+powof2.get(rt+""));}
        else
        {
            System.out.println(rt);
        }
        rt++;
        Preferences.userRoot().put("Pow.run", ""+(rt));
    }
}

1

Javascript

Optei por não usar a log2solução óbvia , mas trabalhei com operadores bit a bit para encontrar a posição de bit único na representação binária de potência de 2 números.

Number.prototype.singleBitPosition = function() {
  var r=1, k;
  if (this==0) return -1;
  while(this==(k=this>>r<<r)) r++; //set r last bits to zero and compare
  return k?-1:r; //if k is zero, there is one single bit to 1 in number representation ie power of 2
};

var n;
if (n === undefined) n=0;
n++;

var e = n.singleBitPosition();
if (e > 0) {
  console.log('2^'+(e-1));
} else {
  console.log(n);
}

ótima estratégia, mas infelizmente o resumo afirma que ele precisa exibir o valor do número de vezes que foi executado, renderizado de acordo ... O seu é apenas um forloop de 1 a 130, com o processamento ...: /
WallyWest

@WallyWest, sim, obrigado por apontar isso.
Michael M.

Sem querer ofender ...
Wally West

11
Não tomei o seu comentário como uma ofensa, foi um verdadeiro agradecimento! Desculpe se minhas palavras não foram bem escolhidas, o inglês não é minha língua materna.
Michael M.

1

Rubi

Tudo bem, acho que vou tentar isso agora. Ele procura a definição de n.

def p2 n
  n == 1 ? 0 : p2(n >> 1) + 1
end
n = 1
if (n != 0) & (n & (n - 1) == 0) || n == 1
  puts("2^" + (p2(n).to_s))
else
  puts n
end

contents = File.read(__FILE__)
newContents = contents.gsub(/(?<=n \= )[0-9]+/) {|n| (n.to_i + 1).to_s}
File.write(__FILE__, newContents)

(testado no Ruby 1.9.3)


1

Fortran 77

Código:

      program twok
      rewind 1
      read(1,'(I20,I3)',end=10,err=30)n,k
      go to 20
10    n=-1
      k=0
20    n=n+1
      if (n .eq. 2**k) then
        if (k.le.9) then
          write(*,'(A3,i1)')' 2^',k
        else
          write(*,'(A3,i2)')' 2^',k
        endif
        k=k+1
      else
        write(*,*)n
      endif
      if (n .lt. 0) then
         n=-1
         k=0
      endif
      rewind 1
      write(1,'(I20,I3)')n,k
30    continue
      end

Resultado:

$ ./a.out       !       $ ./a.out
 2^0            !        2^1
$ ./a.out       !
 2^1            !       $ while true
$ ./a.out       !       > do
 3              !       > ./a.out | grep "2^"
$ ./a.out       !       > done
 2^2            !        2^2
$ ./a.out       !        2^3
 5              !        2^4
$ ./a.out       !        2^5
 6              !        ...
...             !        2^12
$ ./a.out       !        2^13
 2147483647     !       ^C # (after about 5 minutes)
$ ./a.out       !       $ ./a.out
 2^31           !        14718
$ ./a.out       !       $ ./a.out
 0              !        14719
$ ./a.out       !       $
 2^0            !

Isso conta o número de execuções realizadas em um diretório específico. Uma possível melhoria seria solicitar um arquivo no diretório / tmp e adicionar um semáforo para que várias instâncias não tentem atualizar o contador ao mesmo tempo.
Glenn Randers-Pehrson

1

C

Uma das maneiras "apropriadas" de fazer isso (sem usar arquivos, ou seja).

Você pode fornecê-lo resetna linha de comando para configurá-lo novamente como zero. Você também pode mover ou copiar o executável. Mover o executável redefine-o e várias cópias do executável são independentes.

#include <stdio.h>
#include <sys/msg.h>
#include <sys/shm.h>

int main(int argc, char **argv) {
   // get a shared memory segment associated with our program
   long key = ftok(argv[0], 1);
   long id = shmget(key, sizeof(long), 0666 | IPC_CREAT);
   long *num = (long*) shmat(id, NULL, 0);

   // reset parameter
   if (argc == 2 && !strcmp(argv[1], "reset")) {
      *num = 0;
   }

   if (*num & *num-1) {
      // not a power of two
      printf("%li\n", *num);
   } else {
      // power of two
      int exp = 0;
      int n=*num;
      while (n >>= 1) exp++;
      printf("2^%d\n", exp);
   }

   ++*num;

   // detach from shared memory
   shmdt(num);
   return 0;
}

1

Espumante, 423 caracteres (mais um código auto-modificável). Salve-o como count.spndepois execute spn count.spn:

var n =
19
;

var l = log2(n);
if l == floor(l) {
    printf("2 ^ %d\n", floor(l));
} else {
    printf("%.0f\n", n);
}

var f = fopen("count.spn", "rb");
var g = fopen("count.spn.2", "wb");
var line = fgetline(f);
fprintf(g, "%s", line);
fprintf(g, "%d\n", n + 1);
fgetline(f);

while (line = fgetline(f)) != nil {
    fprintf(g, "%s", line);
}

fclose(f);
fclose(g);

0

Aqui está uma solução rápida do Python 3, que usa um arquivo de dados para armazenar ne xentre as execuções:

try:
    with open("count.txt") as f:
        n, x = map(int, f.readline().split())
except FileNotFoundError:
    n = x = 0

n += 1
if n == 2**x:
    print("2^{}".format(x))
    x += 1
else:
    print(n)

with open("count.txt", "w") as f:
    f.write("{} {}".format(n, x))

A saída de executá-lo 16 vezes:

2^0
2^1
3
2^2
5
6
7
2^3
9
10
11
12
13
14
15
2^4

0

Python 2

import inspect
import math

file_name = inspect.getfile(inspect.currentframe())

n = int(open(file_name).readlines()[-1].strip())

l = math.log(n, 2)
if int(l) == l:
    print '2^%d' % (l)
else:
    print n

with open(file_name, 'a') as f:
    f.write('%d\n' % (n + 1))

1

0

C #

static void Main()
{
  ulong cnt         = ++Properties.Settings.Default.NumberOfExecutions ;
  int?  log2        = Log2( cnt ) ;
  Console.WriteLine( log2.HasValue ? "2^{0}" : "{1}" , log2 , cnt ) ;
  Properties.Settings.Default.Save() ;
  return ;
}

static int? Log2( ulong m )
{
  int? n = null ;
  if ( m > 0 )
  {
    n = 0 ;

    // find the first set bit
    ulong mask = 0x0000000000000001ul ;
    while ( mask != 0 && 0ul == (m&mask) )
    {
      mask <<= 1 ;
      ++n ;
    } ;

    // if the mask is identical to m,
    // we've got a power of 2: return n, otherwise null
    n = mask == m ? n : null ;

  }
  return n ;
}

No entanto, isso exige que você defina uma propriedade de configurações no seu projeto do Visual Studio:

captura de tela das configurações do projeto


0

C / POSIX

Este programa usa o número de links físicos para o seu próprio executável como contador da frequência com que foi chamado. Ele cria os novos links físicos no diretório em que foi iniciado (porque dessa forma é garantido que ele esteja no mesmo sistema de arquivos), que, portanto, precisa de permissão de gravação. Omiti o tratamento de erros.

É melhor garantir que você não tenha um arquivo importante com o mesmo nome que um dos links físicos criados nesse diretório, ou ele será substituído. Se, por exemplo, o nome do executável counter, os links físicos serão nomeados counter_1, counter_2etc.

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[])
{
  /* get persistent counter */
  struct stat selfstat;
  stat(argv[0], &selfstat);
  int counter = selfstat.st_nlink;

  /* determine digits of counter */
  int countercopy = counter;
  int digits = 1;
  while (countercopy /= 10)
    ++digits;

  /* increment persistent counter */
  char* newname = malloc(strlen(argv[0]) + digits + 2);
  sprintf(newname, "%s_%d", argv[0], counter);
  link(argv[0], newname);

  /* output the counter */
  if (counter & (counter-1)) // this is zero iff counter is a power of two
    printf("%d\n", counter);
  else
  {
    /* determine which power of 2 it is */
    int power = 0;
    while (counter/=2)
      ++power;
    printf("2^%d\n", power);
  }
  return 0;
}

Exemplo de execução (a primeira linha redefine o contador, caso o executável já tenha sido executado):

$ rm counter_*
$ ./counter
2^0
$ ./counter
2^1
$ ./counter
3
$ ./counter
2^2
$ ./counter
5
$ ./counter
6
$ ./counter
7
$ ./counter
2^3
$ ./counter
9
$ ls counter*
counter    counter_2  counter_4  counter_6  counter_8  counter.c
counter_1  counter_3  counter_5  counter_7  counter_9  counter.c~

0

Fortran 95

Um arquivo chamado "a" (sem extensão) controla a execução do programa.

logical::l
inquire(file="a",exist=l)
open(unit=11,file="a")
if (l) then
  read(11,*)n
  close(unit=11,status="delete")
  open(unit=11,file="a")
  n=n+1
  write(11,*)n
  do i=1,n
    if (2**i==n) then
      write(*,"(A2,I1)")"2^",i
      goto 1        
    endif
  enddo
  print*,n
  else
    print*,"2^0"
    write(11,*)1
endif
1 end
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.