Cada 2 ^ n veces


10

Sea nla cantidad de veces que se ejecutó su programa. Si nes una potencia de 2, imprima 2^xdónde n = 2^x; de lo contrario, simplemente envíe el número. Ejemplo de ejecución:

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

y así. Este es un concurso de popularidad, por lo que la respuesta con más votos positivos gana.


3
¿Por qué sale 0en la primera ejecución?
mniip

¿quiso decir "dónde n = 2^x? De lo contrario, la segunda vez sería la salida 2^4, la cuarta 2^16y así sucesivamente."
John Dvorak

@mniip ambos errores tipográficos. Probablemente debería haberlo leído más cuidadosamente ...: P
Jwosty

44
Umm ... 1es un poder de dos. 2^0=1
John Dvorak

1
Todavía dices en x = 2^xlugar den = 2^x
John Dvorak

Respuestas:


8

Java - Abuso de API

Hay muchas computadoras en línea que pueden contar, así que ¿por qué almacenar el conteo yo mismo?

Abuso total de la API de pila para obtener la cuota y la cuota restante para ver cuántas veces se ha ejecutado hoy:

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, esto solo funciona con una nueva cuota diaria para su IP, y solo hasta la cuota. Si desea soporte para los números más altos, publicar [en funciones solicitud] para elevar 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)

Las alertas sucesivas son las siguientes:

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

Gracias por su amabilidad ... Era la única manera de mantener un registro de las ejecuciones en JavaScript ... Estoy pensando en el uso de almacenamiento local para un próximo juego de JS ...
Wally West

Para algo tan pequeño como un mostrador, una cookie también debería funcionar.
celtschk

@celtschk Gran idea, pero creo que hacer una cookie habría tomado más bytes
WallyWest

6

C - escribir en el ejecutable

Este código C actualiza la cadena dataen el ejecutable, por lo que esencialmente este es un código auto modificable. Si lo ejecutas más de 9,999,999 veces, obtienes cosas interesantes.

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

It segmentación faltas después de compilar con GCC 4.8.1-10ubuntu9: gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla

1
En Mac funciona, no he probado Linux o Windoze. Aparentemente, Linux es más estricto para acceder a ti mismo.
tomsmeding

6

Java

El siguiente código modifica su propio archivo de clase para almacenar el nuevo recuento de ejecución. Esto fue especialmente divertido cuando no tenías idea de cómo se ve el código de bytes, pero después de innumerables horas de Google y Pruebas finalmente funciona. :)

Demostración (utilizando 7 como valor inicial para fines de demostración):

[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

¡Aquí te presento un código portátil! ¡En cada carrera #se agrega un al final, haciendo una barra de progreso! Además, puede mover el código a otra máquina y reanudar desde donde estaba.

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

#

Después de 18 veces:

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, gracias por señalarme este idioma. Incorpora lo que me encanta de Python y Haskell.
Kaya

@Kaya ¡Estoy feliz de que te guste! ¡En caso de que aún no lo haya visto, hay una página de inicio en pyos.github.io/dg y un tutorial también! Un montón de bienes. Y no dude en abrir un problema en el repositorio si lo desea. EDITAR: solo quería señalar que no soy el creador de lang.
rubik

5

Ejemplo de Ruby basado en Sinatra

Esta solución basada en servidor almacena un contador personal para cada usuario en una cookie.

Pruébelo en 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

Aquí hay un poco de perl para hacerlo. ¿Dónde deben almacenarse los datos? ¿Por qué en el archivo del programa en sí, por supuesto! =)

$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 había usado el identificador mágico del archivo DATA de esa manera, pero siento que lo anterior es "más 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

Puede almacenar tell DATAantes de leer, luego buscar de nuevo en ese lugar.
mafia

3

Golpetazo

Script de shell de autoedición simple.

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

Golpetazo

Me gusta la solución Bash de dfernig , pero también me gustaría publicar la mía:

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

Creo que la solución puede considerarse diferente, porque

  • el código realmente ejecutado no cambia
  • el programa calcula dinámicamente si n es una potencia de 2

La "memoria" es el tamaño del script (inicialmente 171 bytes), que se incrementa en 1 con la adición de una nueva línea en cada ejecución.
Las potencias de 2 se reconocen al convertir el tamaño del programa (menos 170, por supuesto) a binario, y luego contar las unidades: si hay exactamente una, entonces n es una potencia de 2. El exponente es el número de ceros en binario .


1

Solución Java

Uing la API de preferencias de Java para almacenar la cantidad de ejecución; y precalculó los poderes de 2 para comparar un hashmap

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

Elegí no usar la log2solución obvia , pero trabajar con operadores bit a bit para encontrar la posición de un solo bit en la representación binaria de la potencia 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);
}

gran estrategia, pero desafortunadamente, el resumen indica que necesita mostrar el valor de la cantidad de veces que se ha ejecutado, procesado en consecuencia ... El suyo es solo un forbucle de 1 a 130, con la representación ...: /
WallyWest

@WallyWest, sí, gracias por señalar esto.
Michael M.

Sin
ánimo de

1
No había tomado tu comentario como una ofensa, ¡eso fue un verdadero agradecimiento! Lo siento si mis palabras no están bien elegidas, el inglés no es mi lengua materna.
Michael M.

1

Rubí

Muy bien, creo que intentaré esto ahora. Busca por sí mismo la definición 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)

(probado en 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            !

Esto cuenta el número de ejecuciones realizadas dentro de un directorio particular. Una posible mejora sería solicitar un archivo en el directorio / tmp y agregar un semáforo para que varias instancias no intenten actualizar el contador al mismo tiempo.
Glenn Randers-Pehrson

1

C

Una de las formas "adecuadas" de hacerlo (sin usar archivos, es decir).

Puede darle reseten la línea de comando para volver a ponerlo a cero. También puede mover o copiar el ejecutable. Al mover el ejecutable, se restablece y varias copias del ejecutable son independientes.

#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

Brillante, 423 caracteres (otro código auto modificable). Guárdelo como count.spnluego ejecutar 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

Aquí hay una solución rápida de Python 3, que utiliza un archivo de datos para almacenar ny xentre ejecuciones:

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

La salida de ejecutarlo 16 veces:

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

Sin embargo, esto requiere que defina una propiedad de configuración en su proyecto de Visual Studio:

captura de pantalla de configuración del proyecto


0

C / POSIX

Este programa usa la cantidad de enlaces duros a su propio ejecutable como contador de la frecuencia con la que se llamó. Crea los nuevos enlaces duros en el directorio desde el que se inició (porque de esa manera se garantiza que estará en el mismo sistema de archivos), por lo que necesita permiso de escritura. He omitido el manejo de errores.

Es mejor que se asegure de no tener un archivo importante con el mismo nombre que uno de los enlaces duros creados en ese directorio, o se sobrescribirá. Si, por ejemplo, se nombra el ejecutable, se nombrarán counterlos enlaces duros 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;
}

Ejemplo de ejecución (la primera línea restablece el contador, en caso de que el ejecutable ya se haya ejecutado):

$ 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

Un archivo llamado "a" (sin extensión) realiza un seguimiento de la ejecución del 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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.