Co 2 ^ n razy

10

Niech nbędzie liczbą wykonań twojego programu. Jeśli njest potęgą 2, wydrukuj 2^xgdzie n = 2^x; w przeciwnym razie po prostu wypisz liczbę. Przykładowy przebieg:

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

i tak dalej. To konkurs popularności, więc wygrywa odpowiedź z największą popularnością.

Jwosty
źródło
3
dlaczego wyświetla się 0w pierwszym uruchomieniu?
mniip
miałeś na myśli „gdzie n = 2^x? W przeciwnym razie po raz drugi wynik byłby 2^4, po raz czwarty 2^16i tak dalej.
John Dvorak
@mniip obie literówki. Prawdopodobnie powinienem był to przeczytać uważniej ...: P
Jwosty
4
Umm ... 1to potęga dwóch. 2^0=1
John Dvorak
1
Nadal mówisz x = 2^xzamiastn = 2^x
John Dvorak

Odpowiedzi:

8

Java - API Abuse

Istnieje wiele komputerów online, które mogą liczyć, więc po co przechowywać te liczby osobiście?

Całkowite nadużycie interfejsu API stosu w celu uzyskania limitu i pozostałego limitu, aby zobaczyć, ile razy został uruchomiony dzisiaj:

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

Oczywiście działa to tylko ze świeżym dziennym przydziałem dla twojego adresu IP i tylko do limitu. Jeśli chcesz wsparcie dla wyższych liczb, napisać wniosek [funkcje], aby podnieść quota_maxsię MAX_INT.

Geobity
źródło
6

JavaScript

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

Kolejne alerty są następujące:

2^0
2^1
3
2^2
5
6
7
2^3
9
...and so on.
WallyWest
źródło
Dziękuję uprzejmie ... Był to jedyny sposób, aby śledzić wykonanie w JavaScript ...
Rozważam użycie localStorage
W przypadku czegoś tak małego jak licznik plik cookie powinien również działać.
celtschk
@celtschk Świetny pomysł, ale wierzę, że zrobienie ciasteczka zajęłoby więcej bajtów
WallyWest
6

C - pisanie do pliku wykonywalnego

Ten kod C aktualizuje ciąg dataw pliku wykonywalnym, więc zasadniczo jest to kod samodmodyfikujący. Jeśli uruchomisz go 9 999 999 razy, otrzymasz ciekawe rzeczy.

#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
źródło
IT segmentacji usterek po kompilacji ją GCC 4.8.1-10ubuntu9: gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla
1
Na Macu to działa, nie próbowałem Linuksa ani Windoze. Najwyraźniej Linux ma bardziej rygorystyczny dostęp do siebie.
tomsmeding
6

Jawa

Poniższy kod modyfikuje własny plik klasy w celu zapisania nowej liczby uruchomień. Było to szczególnie zabawne, gdy nie miałeś pojęcia, jak wygląda kod bajtowy, ale po niezliczonych godzinach Googlingu i testowania w końcu działa! :)

Demo (użycie 7 jako wartości początkowej do celów demonstracyjnych):

[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

Kod:

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
źródło
5

dg

Tutaj przedstawiam Ci przenośny kod! Na każdym biegu #dodaje się a na końcu, tworząc pasek postępu! Możesz także przenieść kod na inną maszynę i wznowić od miejsca, w którym byłeś.

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

#

Po 18 razy:

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
źródło
Achh, dzięki za wskazanie mi tego języka. Zawiera to, co kocham zarówno w Pythonie, jak i Haskell.
Kaya
@Kaya Cieszę się, że ci się podoba! Jeśli jeszcze tego nie widziałeś, jest strona główna na pyos.github.io/dg, a także samouczek! Dużo towarów. I nie wahaj się otworzyć problemu w repozytorium, jeśli masz na to ochotę. EDYCJA: Chciałem tylko zaznaczyć, że nie jestem twórcą języka.
rubik
5

Przykład Ruby oparty na Sinatrze

To rozwiązanie serwerowe przechowuje osobisty licznik dla każdego użytkownika w pliku cookie.

Wypróbuj na 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
Steve Wilhelm
źródło
5

perl

Oto krótki perl, aby to zrobić. Gdzie powinny być przechowywane dane? Oczywiście w samym pliku programu! =)

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

Pierwotnie użyłem magicznego uchwytu pliku DATA, ale czuję, że powyższe jest „czystsze”:

$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
źródło
Możesz przechowywać tell DATAprzed przeczytaniem, a następnie wrócić do tego miejsca.
tłum
3

Grzmotnąć

Prosty skrypt powłoki do samodzielnej edycji.

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
źródło
2

Grzmotnąć

I jak dfernig „s rozwiązanie bash , ale chciałbym, aby umieścić kopalni, a także:

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

Myślę, że rozwiązanie można uznać za inne, ponieważ

  • faktycznie wykonany kod się nie zmienia
  • program oblicza dynamicznie, czy n jest potęgą 2

„Pamięć” to rozmiar skryptu (początkowo 171 bajtów), który jest powiększany o 1 wraz z dodawaniem nowego wiersza przy każdym wykonaniu.
Potęgi 2 są rozpoznawane przez konwersję rozmiaru programu (minus 170, oczywiście) na binarne, a następnie zliczenie tych: jeśli jest dokładnie jeden, to n jest potęgą 2. Wykładnik to liczba zer w binarnych .

scristalli
źródło
1

Rozwiązanie Java

Użycie interfejsu API preferencji Java do przechowywania kwoty uruchomienia; i wstępnie obliczył potęgę 2 dla porównania

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
źródło
1

JavaScript

Nie zdecydowałem się na oczywiste log2rozwiązanie, ale pracowałem z operatorami bitowymi, aby znaleźć pozycję pojedynczego bitu w binarnej reprezentacji potęgi 2 liczb.

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.
źródło
świetna strategia, ale niestety w streszczeniu stwierdza się, że musi wyświetlać wartość liczby wykonanych operacji, odpowiednio renderowanych ... Twoja forpętla jest od 1 do 130, z renderowaniem ...: /
WallyWest,
@WallyWest, tak, dziękuję za zwrócenie na to uwagi.
Michael M.
Bez przestępstwa przeznaczony ...
WallyWest
1
Nie wziąłem twojego komentarza za przestępstwo, to było naprawdę dzięki! Przepraszam, jeśli moje słowa nie są dobrze wybrane, angielski nie jest moim językiem ojczystym.
Michael M.
1

Rubin

Dobra, chyba spróbuję tego teraz. Sam szuka definicji 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)

(testowany w Ruby 1.9.3)

Jwosty
źródło
1

Fortran 77

Kod:

      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

Wynik:

$ ./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
źródło
Zlicza to liczbę uruchomień wykonanych w danym katalogu. Możliwym ulepszeniem byłoby zażądanie pliku w katalogu / tmp i dodanie semafora, aby wiele instancji nie próbowało aktualizować licznika w tym samym czasie.
Glenn Randers-Pehrson
1

do

Jeden z „właściwych” sposobów na zrobienie tego (bez używania plików).

Możesz podać go resetw wierszu poleceń, aby ustawić go ponownie na zero. Możesz także przenieść lub skopiować plik wykonywalny. Przeniesienie pliku wykonywalnego resetuje go, a wiele kopii pliku wykonywalnego jest niezależnych.

#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
źródło
1

Musujące, 423 znaki (kolejny kod samodmodyfikujący). Zapisz go, a count.spnnastępnie uruchom 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
źródło
0

Oto szybkie rozwiązanie Python 3, które używa pliku danych do przechowywania ni xmiędzy uruchomieniami:

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

Wydajność jego uruchomienia 16 razy:

2^0
2^1
3
2^2
5
6
7
2^3
9
10
11
12
13
14
15
2^4
Blckknght
źródło
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
źródło
0

DO#

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

Wymaga to jednak zdefiniowania właściwości ustawień w projekcie Visual Studio:

Zrzut ekranu ustawień projektu

Nicholas Carey
źródło
0

C / POSIX

Ten program wykorzystuje liczbę twardych dowiązań do własnego pliku wykonywalnego jako licznik tego, jak często był wywoływany. Tworzy nowe twarde dowiązania w katalogu, z którego został uruchomiony (ponieważ w ten sposób gwarantuje to, że znajduje się w tym samym systemie plików), co wymaga uprawnień do zapisu. Pominąłem obsługę błędów.

Lepiej upewnij się, że nie masz ważnego pliku o takiej samej nazwie jak jeden z utworzonych twardych linków w tym katalogu, w przeciwnym razie zostanie on nadpisany. Jeśli na przykład plik wykonywalny nazywa counter, twarde linki zostaną nazwane 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;
}

Przykład uruchomienia (pierwszy wiersz resetuje licznik, jeśli plik wykonywalny został już uruchomiony):

$ 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
źródło
0

Fortran 95

Plik o nazwie „a” (bez rozszerzenia) śledzi przebieg programu.

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
źródło