Ogni 2 ^ n volte


10

Indica nil numero di volte in cui il tuo programma è stato eseguito. Se nè una potenza di 2, quindi stampare 2^xdove n = 2^x; in caso contrario, semplicemente emettere il numero. Esempio di esecuzione:

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

e così via. Questo è un concorso di popolarità, quindi vince la risposta con più voti.


3
perché viene emesso 0al primo avvio?
mniip,

volevi dire "dove n = 2^x? Altrimenti la seconda volta che sarebbe uscita 2^4, la quarta volta 2^16e così via.
John Dvorak

@mniip entrambi i refusi. Probabilmente avrei dovuto leggerlo più attentamente ...: P
Jwosty

4
Umm ... 1è un potere di due. 2^0=1
John Dvorak,

1
Dici ancora x = 2^xpiuttosto chen = 2^x
John Dvorak il

Risposte:


8

Java - Abuso dell'API

Ci sono molti computer online che possono contare, quindi perché archiviare il conteggio da solo?

Abuso completo dell'API Stack per ottenere la quota e la quota rimanente per vedere quante volte è stata eseguita oggi:

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

Ovviamente questo funziona solo con una nuova quota giornaliera per il tuo IP e solo fino alla quota. Se si desidera che il supporto per i numeri più alti, inviare un [caratteristica-request] per aumentare 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)

Gli avvisi successivi sono i seguenti:

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

Grazie gentilmente ... "È stato l'unico modo per tenere traccia delle esecuzioni in JavaScript ... Sto pensando di utilizzare localStorage per un prossimo gioco di JS ...
WallyWest

Per qualcosa di piccolo come un contatore, dovrebbe funzionare anche un cookie.
Celtschk,

@celtschk Ottima idea, ma credo che creare un cookie avrebbe richiesto più byte
WallyWest

6

C - scrivendo all'eseguibile

Questo codice C aggiorna la stringa datanell'eseguibile, quindi essenzialmente si tratta di codice auto-modificante. Se lo esegui più di 9.999.999 volte, otterrai cose interessanti.

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

Esso segmentazione errori dopo la compilazione con GCC 4.8.1-10ubuntu9: gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla

1
Su Mac funziona, non ho provato Linux o Windoze. Apparentemente Linux è più severo con l'accesso a te stesso.
tomsmeding

6

Giava

Il codice seguente modifica il proprio file di classe per memorizzare il nuovo conteggio delle esecuzioni. Questo è stato particolarmente divertente quando non avevi idea dell'aspetto del codice byte, ma dopo innumerevoli ore di ricerca su Google e test finalmente funziona! :)

Demo (usando 7 come valore iniziale per scopi dimostrativi):

[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

Codice:

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

Qui ti presento un codice portatile! Ad ogni corsa #viene aggiunto un alla fine, facendo una barra di avanzamento! Inoltre, puoi spostare il codice su un altro computer e riprendere da dove eri.

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

#

Dopo 18 volte:

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

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

Ah, grazie per avermi indicato questa lingua. Incorpora ciò che amo sia di Python che di Haskell.
Kaya

@Kaya Sono felice che ti piaccia! Se non l'hai già visto, c'è una homepage su pyos.github.io/dg e anche un tutorial! Un sacco di merci. E non esitare ad aprire un problema sul repository se lo desideri. EDIT: volevo solo sottolineare che non sono il creatore della lingua.
rubik

5

Esempio di Ruby basato su Sinatra

Questa soluzione basata su server memorizza un contatore personale per ciascun utente in un cookie.

Provalo su 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

Ecco un po 'di perl per farlo. Dove dovrebbero essere archiviati i dati? Perché nel file del programma stesso, ovviamente! =)

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

Inizialmente avevo usato la gestione magica del file DATA in questo modo, ma penso che quanto sopra sia "più 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

Puoi memorizzare tell DATAprima di leggere da esso, quindi cercare di nuovo in quel punto.
mob

3

bash

Semplice script shell auto-editing.

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

bash

Mi piace la soluzione Bash di dfernig , ma vorrei pubblicare anche la mia:

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

Penso che la soluzione possa essere considerata diversa, perché

  • il codice effettivamente eseguito non cambia
  • il programma calcola dinamicamente se n è una potenza di 2

La "memoria" è la dimensione dello script (inizialmente 171 byte), che viene aumentata di 1 con l'appendice di una nuova riga a ogni esecuzione.
I poteri di 2 sono riconosciuti convertendo la dimensione del programma (meno 170, ovviamente) in binario, quindi contando quelli: se ce n'è esattamente uno, allora n è una potenza di 2. L'esponente è il numero di zeri in binario .


1

Soluzione Java

Utilizzo dell'API delle preferenze Java per memorizzare l'importo della corsa; e ha pre-calcolato i poteri di 2 per un hashmap da confrontare

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

Ho scelto di non usare la log2soluzione ovvia , ma di lavorare con operatori bit a bit per trovare la posizione a bit singolo nella rappresentazione binaria della potenza di 2 numeri.

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

ottima strategia, ma purtroppo il breve afferma che deve mostrare il valore del numero di volte che è stato eseguito, reso di conseguenza ... Il tuo è solo un forloop da 1 a 130, con il rendering ...: /
WallyWest

@WallyWest, sì, grazie per averlo segnalato.
Michael M.

Nessuna offesa voluta ...
WallyWest

1
Non avevo preso il tuo commento come un'offesa, è stato un vero ringraziamento! Scusate se le mie parole non sono ben scelte, l'inglese non è la mia lingua madre.
Michael M.

1

Rubino

Bene, penso che ci proverò ora. Si cerca la definizione di 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)

(testato in Ruby 1.9.3)


1

Fortran 77

Codice:

      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

Risultato:

$ ./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            !

Ciò conta il numero di esecuzioni eseguite all'interno di una directory specifica. Il possibile miglioramento sarebbe richiedere un file nella directory / tmp e aggiungere un semaforo in modo che più istanze non provino ad aggiornare il contatore contemporaneamente.
Glenn Randers-Pehrson

1

C

Uno dei modi "corretti" per farlo (senza usare i file, cioè).

Puoi assegnarlo resetdalla riga di comando per riportarlo a zero. Puoi anche spostare o copiare il file eseguibile. Lo spostamento dell'eseguibile lo ripristina e più copie dell'eseguibile sono indipendenti.

#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

Scintillante, 423 caratteri (ancora un altro codice automodificante). Salvalo come count.spnquindi esegui 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

Ecco una rapida soluzione Python 3, che utilizza un file di dati per archiviare ne xtra le esecuzioni:

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

L'output di eseguirlo 16 volte:

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

Questo, tuttavia, richiede che tu definisca una proprietà settings nel tuo progetto Visual Studio:

schermata delle impostazioni del progetto


0

C / POSIX

Questo programma utilizza il numero di collegamenti fisici al proprio eseguibile come contatore della frequenza con cui è stato chiamato. Crea i nuovi hard link nella directory da cui è stato avviato (perché in questo modo è garantito che si trovi sullo stesso file system), che quindi necessita dell'autorizzazione in scrittura. Ho omesso la gestione degli errori.

È meglio assicurarsi di non avere file importanti con lo stesso nome di uno dei collegamenti reali creati in quella directory, altrimenti verrà sovrascritto. Se ad esempio viene chiamato l'eseguibile counter, verranno nominati i collegamenti reali counter_1, counter_2ecc.

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

Esempio di esecuzione (la prima riga reimposta il contatore, nel caso in cui sia già stato eseguito l'eseguibile):

$ 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 file chiamato "a" (senza estensione) tiene traccia dell'esecuzione del programma.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.