Alle 2 ^ n mal

10

Geben Sie an n, wie oft Ihr Programm ausgeführt wurde. Wenn neine Potenz von 2 ist, drucken Sie 2^xwo n = 2^x; Andernfalls geben Sie einfach die Nummer aus. Beispiellauf:

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

und so weiter. Dies ist ein Beliebtheitswettbewerb, daher gewinnt die Antwort mit den meisten positiven Stimmen.

Jwosty
quelle
3
Warum wird es 0im ersten Durchgang ausgegeben ?
Mniip
Meinten Sie "wo n = 2^x? Andernfalls wäre die Ausgabe das zweite Mal 2^4, das vierte Mal 2^16und so weiter.
John Dvorak
@mniip beide Tippfehler. Ich hätte das wahrscheinlich genauer lesen sollen ...: P
Jwosty
4
Umm ... 1ist eine Zweierpotenz. 2^0=1
John Dvorak
1
Sie sagen immer noch x = 2^xeher alsn = 2^x
John Dvorak

Antworten:

8

Java - API Missbrauch

Es gibt viele Computer online, die zählen können. Warum also die Zählung selbst speichern?

Vollständiger Missbrauch der Stack-API, um das Kontingent zu erhalten, und das verbleibende Kontingent, um zu sehen, wie oft sie heute ausgeführt wurde:

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

Offensichtlich funktioniert dies nur mit einem neuen Tageskontingent für Ihre IP und nur bis zum Kontingent. Wenn Sie Unterstützung für höhere Zahlen möchten, senden Sie uns eine [Feature-Anfrage] heben quota_maxzu MAX_INT.

Geobits
quelle
6

JavaScript

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

Aufeinanderfolgende Warnungen lauten wie folgt:

2^0
2^1
3
2^2
5
6
7
2^3
9
...and so on.
WallyWest
quelle
Vielen Dank ... 'Es war die einzige Möglichkeit, die Ausführung in JavaScript zu verfolgen ... Ich denke darüber nach, localStorage für ein bevorstehendes JS-Spiel zu verwenden ...
WallyWest
Für etwas so Kleines wie eine Theke sollte auch ein Cookie funktionieren.
Celtschk
@ Celtschk Tolle Idee, aber ich glaube, ein Cookie zu machen hätte mehr Bytes
gekostet
6

C - Schreiben in die ausführbare Datei

Dieser C-Code aktualisiert die Zeichenfolge datain der ausführbaren Datei, sodass es sich im Wesentlichen um selbstmodifizierenden Code handelt. Wenn Sie es über 9.999.999 Mal ausführen, erhalten Sie interessante Dinge.

#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;
}
Tomsmeding
quelle
Es Segmentierungsfehler nach dem Kompilieren mit GCC 4.8.1-10ubuntu9 : gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla
1
Auf dem Mac funktioniert es, ich habe weder Linux noch Windoze ausprobiert. Anscheinend ist Linux strenger beim Zugriff auf sich selbst.
Tomsmeding
6

Java

Der folgende Code ändert die eigene Klassendatei, um die neue Laufanzahl zu speichern. Das hat besonders Spaß gemacht, als Sie keine Ahnung hatten, wie der Bytecode aussieht, aber nach unzähligen Stunden Googeln und Testen funktioniert es endlich! :) :)

Demo (mit 7 als Startwert für Demozwecke):

[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

Code:

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:
            }
        }
    }
}
TimWolla
quelle
5

dg

Hier präsentiere ich Ihnen einen tragbaren Code! Bei jedem Lauf #wird am Ende ein hinzugefügt, wodurch ein Fortschrittsbalken erstellt wird! Sie können den Code auch auf einen anderen Computer verschieben und von Ihrem Standort aus fortfahren.

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

#

Nach 18 mal:

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

###################
rubik
quelle
Ahh, danke, dass du mich auf diese Sprache aufmerksam gemacht hast. Es enthält das, was ich an Python und Haskell liebe.
Kaya
@ Kaya Ich bin froh, dass es dir gefällt! Falls Sie es noch nicht gesehen haben, gibt es eine Homepage unter pyos.github.io/dg und ein Tutorial! Viele Waren. Und zögern Sie nicht, ein Problem im Repository zu öffnen, wenn Sie dies wünschen. EDIT: Ich wollte nur darauf hinweisen, dass ich nicht der Schöpfer der Sprache bin.
Rubik
5

Sinatra-basiertes Ruby-Beispiel

Diese serverbasierte Lösung speichert einen persönlichen Zähler für jeden Benutzer in einem Cookie.

Probieren Sie es unter http://every-2-to-the-n-times.herokuapp.com/ aus.

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
Steve Wilhelm
quelle
5

Perl

Hier ist ein bisschen Perl, um es zu tun. Wo sollen die Daten gespeichert werden? Warum in der Programmdatei selbst natürlich! =)

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

Ursprünglich hatte ich das magische DATA-Dateihandle so verwendet, aber ich denke, das oben genannte ist "reiner":

$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
skibrianski
quelle
Sie können speichern, tell DATAbevor Sie daraus lesen, und dann zu dieser Stelle zurückkehren.
Mob
3

Bash

Einfaches selbstbearbeitendes Shell-Skript.

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
dfernig
quelle
2

Bash

Ich mag die Bash-Lösung von dfernig , aber ich möchte auch meine posten:

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

Ich denke, die Lösung kann als anders angesehen werden, weil

  • Der tatsächlich ausgeführte Code ändert sich nicht
  • Das Programm berechnet dynamisch, ob n eine Potenz von 2 ist

Der "Speicher" ist die Skriptgröße (anfänglich 171 Byte), die bei jeder Ausführung mit dem Anhängen einer neuen Zeile um 1 erhöht wird.
Potenzen von 2 werden erkannt, indem die Programmgröße (natürlich minus 170) in Binär konvertiert und dann die Einsen gezählt werden: Wenn es genau eine Eins gibt, ist n eine Potenz von 2. Der Exponent ist die Anzahl der Nullen in Binär .

scristalli
quelle
1

Java-Lösung

Verwenden Sie die Java-Einstellungs-API, um den Ausführungsbetrag zu speichern. und berechnete die Potenzen von 2 vor, damit eine Hashmap verglichen werden kann

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));
    }
}
masterX244
quelle
1

Javascript

Ich habe mich dafür entschieden, nicht die offensichtliche log2Lösung zu verwenden, sondern mit bitweisen Operatoren zu arbeiten, um die Einzelbitposition in der binären Darstellung der Potenz von 2 Zahlen zu finden.

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);
}
Michael M.
quelle
Tolle Strategie, aber leider besagt der Brief, dass der Wert angezeigt werden muss, wie oft er ausgeführt und entsprechend gerendert wurde ... Ihre ist nur eine forSchleife von 1 bis 130 mit dem Rendering ...: /
WallyWest
@WallyWest, ja, danke, dass du darauf hingewiesen hast.
Michael M.
Keine Straftat beabsichtigt ...
WallyWest
1
Ich hatte Ihren Kommentar nicht als Straftat angesehen, das war ein echter Dank! Entschuldigung, wenn meine Worte nicht gut gewählt sind, ist Englisch nicht meine Muttersprache.
Michael M.
1

Rubin

Okay, ich denke ich werde es jetzt versuchen. Es sucht sich nach der Definition von 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)

(getestet in Ruby 1.9.3)

Jwosty
quelle
1

Fortran 77

Code:

      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

Ergebnis:

$ ./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            !
Glenn Randers-Pehrson
quelle
Dies zählt die Anzahl der Läufe in einem bestimmten Verzeichnis. Eine mögliche Verbesserung wäre, eine Datei im Verzeichnis / tmp anzufordern und ein Semaphor hinzuzufügen, damit mehrere Instanzen nicht gleichzeitig versuchen, den Zähler zu aktualisieren.
Glenn Randers-Pehrson
1

C.

Eine der "richtigen" Möglichkeiten, dies zu tun (dh ohne Verwendung von Dateien).

Sie können es resetin der Befehlszeile eingeben, um es wieder auf Null zu setzen. Sie können die ausführbare Datei auch verschieben oder kopieren. Durch Verschieben der ausführbaren Datei wird sie zurückgesetzt, und mehrere Kopien der ausführbaren Datei sind unabhängig voneinander.

#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;
}
Marinus
quelle
1

Funkelnd, 423 Zeichen (ein weiterer selbstmodifizierender Code). Speichern Sie es als count.spndann ausführen 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);
H2CO3
quelle
0

Hier ist eine schnelle Python 3-Lösung, die zum Speichern nund xzwischen Läufen eine Datendatei verwendet :

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

Die Ausgabe von 16-mal ausführen:

2^0
2^1
3
2^2
5
6
7
2^3
9
10
11
12
13
14
15
2^4
Blckknght
quelle
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
Jayanth Koushik
quelle
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 ;
}

Dies erfordert jedoch, dass Sie eine Einstellungseigenschaft in Ihrem Visual Studio-Projekt definieren:

Screenshot der Projekteinstellungen

Nicholas Carey
quelle
0

C / POSIX

Dieses Programm verwendet die Anzahl der festen Links zu seiner eigenen ausführbaren Datei als Zähler dafür, wie oft es aufgerufen wurde. Es erstellt die neuen Hardlinks in dem Verzeichnis, aus dem es gestartet wurde (da es sich auf diese Weise garantiert im selben Dateisystem befindet), für das daher eine Schreibberechtigung erforderlich ist. Ich habe die Fehlerbehandlung weggelassen.

Stellen Sie besser sicher, dass Sie keine wichtige Datei mit demselben Namen wie einer der erstellten Hardlinks in diesem Verzeichnis haben, da diese sonst überschrieben wird. Wenn beispielsweise die ausführbare Datei benannt ist counter, werden die Hardlinks genannt werden counter_1, counter_2usw.

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

Beispiellauf (die erste Zeile setzt den Zähler zurück, falls die ausführbare Datei bereits ausgeführt wurde):

$ 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~
Celtschk
quelle
0

Fortran 95

Eine Datei mit dem Namen "a" (ohne Erweiterung) verfolgt den Programmablauf.

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
gilbertohasnofb
quelle