Her 2 ^ n seferde


10

Izin vermek nprogramın kaç kez yürütüldü. n2 gücü varsa , o zaman 2^xnereye yazdırın n = 2^x; Aksi takdirde, numarayı çıkarmanız yeterlidir. Örnek çalışma:

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

ve bunun gibi. Bu bir popülerlik yarışması, bu yüzden en çok oy alan cevap kazanıyor ..


3
neden 0ilk seferde çıktı ?
Mart'ta mniip

n = 2^xYoksa "nerede ? Çıktı ikinci kez 2^4, dördüncü kez 2^16ve benzeri olur.
John Dvorak

mnip her iki yazım hatası. Muhtemelen bunu daha dikkatli
okumalıydım

4
Hımm ... ikinin 1gücüdür. 2^0=1
John Dvorak

1
Hala söylemek x = 2^xyerinen = 2^x
John Dvorak

Yanıtlar:


8

Java - API Kötüye Kullanımı

Çevrimiçi sayabileceğiniz birçok bilgisayar var, bu yüzden neden sayımı kendim saklayayım?

Kota almak için Stack API'sını tam olarak kötüye kullanma ve bugün kaç kez çalıştırıldığını görmek için kalan kota:

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

Açıkçası bu yalnızca IP için bir taze günlük kota ile çalışır ve sadece en fazla kota. Daha yüksek numaralar için destek istiyorsanız, yükseltmek quota_maxiçin bir [özellik isteği] gönderin MAX_INT.


6

JavaScript

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

Ardışık uyarılar aşağıdaki gibidir:

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

Nazikçe teşekkür ederim ... 'Twas, JavaScript'teki yürütmeleri takip etmenin tek yolu ... Yaklaşan bir JS oyunu için localStorage'ı kullanmayı düşünüyorum ...
WallyWest

Sayaç kadar küçük bir şey için, bir çerez de çalışmalıdır.
celtschk

@celtschk Harika bir fikir, ama bir çerez yapmanın daha fazla bayt alacağına inanıyorum
WallyWest

6

C - yürütülebilir dosyaya yazma

Bu C kodu data, yürütülebilir dosyadaki dizeyi günceller , bu nedenle bu kendi kendini değiştiren koddur. 9.999.999 kez çalıştırırsanız, ilginç şeyler alırsınız.

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

: Bu segmentasyon hataları GCC 4.8.1-10ubuntu9 ile derleme sonra gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla

1
Mac'te çalışıyor, Linux veya Windoze'i denemedim. Görünüşe göre Linux kendinize erişim konusunda daha katı.
Mart'ta tomsmeding

6

Java

Aşağıdaki kod, yeni çalışma sayısını depolamak için kendi sınıf dosyasını değiştirir. Bayt kodunun nasıl göründüğüne dair hiçbir fikriniz olmadığında özellikle eğlenceliydi, ancak sayısız saat Googling and Testing'den sonra nihayet işe yaradı! :)

Demo (demo amacıyla başlangıç ​​değeri olarak 7 kullanarak):

[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:
            }
        }
    }
}

5

dg

Burada size taşınabilir bir kod sunuyorum! Her çalıştırmada #a ilerleme çubuğu yaparak sonuna eklenir! Ayrıca, kodu başka bir makineye taşıyabilir ve bulunduğunuz yerden devam edebilirsiniz.

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

#

18 kez sonra:

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, bu dili bana gösterdiğin için teşekkürler. Hem Python hem de Haskell hakkında sevdiğim şeyleri içeriyor.
Kaya

@Kaya Beğendiğine sevindim! Henüz görmediyseniz, pyos.github.io/dg adresinde bir ana sayfa ve bir eğitim de vardır! Çok fazla mal. İsterseniz depoda bir sorun açmaktan çekinmeyin. EDIT: Ben sadece lang yaratıcısı olmadığını işaret etmek istedim.
rubik

5

Sinatra Temelli Yakut Örneği

Bu sunucu tabanlı çözüm, çerezdeki her kullanıcı için kişisel bir sayaç depolar.

Http://every-2-to-the-n-times.herokuapp.com/ adresinden deneyin.

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

İşte bunu yapmak için kısa bir perl. Veriler nerede saklanmalıdır? Neden program dosyasında, tabii ki! =)

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

Başlangıçta böyle sihirli DATA dosya tanıtıcısı kullanmıştım, ama yukarıda "daha saf" olduğunu hissediyorum:

$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

Ondan tell DATAokumadan önce saklayabilir , sonra o noktaya geri dönebilirsiniz.
mafya

3

darbe

Basit kendi kendini düzenleyen kabuk betiği.

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

darbe

Gibi dfernig 'ın Bash çözümü , ama ben de benimkini nakletmek istiyorum:

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

Bence çözüm farklı sayılabilir, çünkü

  • gerçekte yürütülen kod değişmez
  • program n'nin 2'nin gücü olup olmadığını dinamik olarak hesaplar

"Bellek" komut dosyası boyutudur (başlangıçta 171 bayt), her yürütmede bir satırsonu ekleyerek 1 arttırılır.
2'nin gücü , program boyutunu (eksi 170, elbette) ikiliye dönüştürerek ve sonra ikisini sayarak tanınır: tam olarak bir tane varsa, n 2'nin gücüdür. Üs, ikili dosyadaki sıfır sayısıdır. .


1

Java çözümü

Çalıştırma miktarını saklamak için java tercihleri ​​API'sini kullanma; karşılaştırmak için bir hashmap 2 güçlerini önceden hesapladı

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

Açık log2çözümü kullanmamayı seçtim, ancak 2 sayının iktidarının ikili gösteriminde tek bit konumunu bulmak için bitsel operatörlerle çalışmayı seçtim .

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

Büyük strateji, ama ne yazık ki, kısa devletler bu Seninki sadece bir olduğunu ... buna göre render idam edildikten kaç kez değerini görüntülemek için ihtiyaç duyduğu forrender ile, 1'den 130'a döngü ...: /
WallyWest

@WallyWest, evet, bunu belirttiğin için teşekkürler.
Michael


1
Yorumunuzu bir suç olarak almamıştım, bu gerçek bir teşekkürdü! Kelimelerim iyi seçilmiş değilse özür dilerim, ingilizce anadilim değil.
Michael

1

Yakut

Tamam, sanırım şimdi deneyeceğim. Kendisinin tanımını arar 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)

(Ruby 1.9.3'te test edilmiştir)


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

Sonuç:

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

Bu, belirli bir dizinde yapılan çalışma sayısını sayar. Olası iyileştirme, / tmp dizininde bir dosya istemek ve birden çok örneğin sayacı aynı anda güncelleştirmeye çalışmaması için bir semafor eklemek olacaktır.
Glenn Randers-Pehrson

1

C

Bunu yapmanın "uygun" yollarından biri (yani dosyaları kullanmadan).

resetSıfıra geri ayarlamak için komut satırında verebilirsiniz . Yürütülebilir dosyayı da taşıyabilir veya kopyalayabilirsiniz. Yürütülebilir dosyayı taşımak sıfırlar ve yürütülebilir dosyanın birden çok kopyası bağımsızdır.

#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

Köpüklü, 423 karakter (yine başka bir kendini değiştiren kod). Farklı kaydedin ve count.spnçalıştırın 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

İşte depolamak nve xçalışır arasında bir veri dosyası kullanan hızlı bir Python 3 çözümü :

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

16 kez çalıştırmanın çıktısı:

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

Ancak bu, Visual Studio projenizde bir settings özelliği tanımlamanızı gerektirir:

proje ayarları ekran görüntüsü


0

Cı / POSIX

Bu program, ne sıklıkta çağrıldığının sayacı olarak kendi yürütülebilir dosyasına sabit bağlantı sayısını kullanır. Başlatıldığı dizinde yeni sabit bağlantıları oluşturur (bu nedenle aynı dosya sisteminde olması garanti edilir), bu nedenle yazma iznine ihtiyaç duyar. Hata işlemeyi atladım.

Bu dizinde oluşturulan sabit bağlantılardan biriyle aynı ada sahip önemli bir dosyanız olmadığından emin olmanız gerekir, aksi takdirde dosyanın üzerine yazılır. Yürütülebilir örneğin adı verilirse counter, sabit bağlantılar ismi verilecek counter_1, counter_2vs.

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

Örnek run (yürütülebilir dosya zaten çalıştırılmışsa ilk satır sayacı sıfırlar):

$ 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

"A" adlı bir dosya (uzantısız) programın çalışmasını izler.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.