Cứ sau 2 ^ n lần


10

Hãy nlà số lần chương trình của bạn đã được thực hiện. Nếu nlà lũy thừa 2 thì in 2^xở đâu n = 2^x; mặt khác, chỉ cần xuất số. Chạy ví dụ:

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

và như thế. Đây là một cuộc thi phổ biến, vì vậy câu trả lời có nhiều người chiến thắng nhất ..


3
Tại sao nó xuất ra 0trong lần chạy đầu tiên?
mniip

ý bạn là "ở đâu n = 2^x? Nếu không thì lần thứ hai đầu ra sẽ là 2^4lần thứ tư 2^16, v.v.
John Dvorak

@mniip cả lỗi chính tả. Có lẽ tôi nên đọc kỹ hơn ...: P
Jwosty

4
Umm ... 1là một sức mạnh của hai. 2^0=1
John Dvorak

1
Bạn vẫn nói x = 2^xchứ không phảin = 2^x
John Dvorak

Câu trả lời:


8

Lạm dụng Java - API

Có rất nhiều máy tính trực tuyến có thể đếm, vậy tại sao lại tự lưu trữ số đếm?

Lạm dụng đầy đủ API Stack để lấy hạn ngạch và hạn ngạch còn lại để xem số lần chạy của nó hôm nay là bao nhiêu lần:

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

Rõ ràng điều này chỉ hoạt động với hạn ngạch mới hàng ngày cho IP của bạn và chỉ tối đa dung lượng. Nếu bạn muốn hỗ trợ cho các số cao hơn, hãy đăng [yêu cầu tính năng] để nâng quota_maxlên MAX_INT.


6

JavaScript

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

Thông báo liên tiếp như sau:

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

Xin chân thành cảm ơn ... 'Twas cách duy nhất để theo dõi các vụ hành quyết trong JavaScript ... Tôi đang cân nhắc sử dụng localStorage cho một trò chơi JS sắp tới ...
WallyWest

Đối với một cái gì đó nhỏ như một quầy, một cookie cũng nên hoạt động.
celtschk

@celtschk Ý tưởng tuyệt vời, nhưng tôi tin rằng việc tạo một cookie sẽ mất nhiều byte hơn
WallyWest

6

C - viết cho người thực thi

Mã C này cập nhật chuỗi datatrong tệp thực thi, vì vậy về cơ bản đây là mã tự sửa đổi. Nếu bạn chạy nó hơn 9,999.999 lần, bạn sẽ nhận được những thứ thú vị.

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

Nó phân đoạn lỗi sau khi biên dịch nó với GCC 4.8.1-10ubfox9 : gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla

1
Trên Mac, nó hoạt động, chưa thử Linux hoặc Windoze. Rõ ràng Linux nghiêm ngặt hơn với việc truy cập chính mình.
tomsmeding

6

Java

Đoạn mã sau sửa đổi tệp lớp riêng của nó để lưu trữ số lần chạy mới. Điều này đặc biệt thú vị khi bạn không biết mã byte trông như thế nào, nhưng sau vô số giờ làm việc và thử nghiệm, cuối cùng nó cũng hoạt động! :)

Bản trình diễn (sử dụng 7 làm giá trị bắt đầu cho mục đích demo):

[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

Mã số:

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

đg

Ở đây tôi trình bày cho bạn một mã di động! Tại mỗi lần chạy a #được thêm vào cuối, tạo một thanh tiến trình! Ngoài ra, bạn có thể di chuyển mã sang máy khác và tiếp tục từ nơi bạn đã ở.

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

#

Sau 18 lần:

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, cảm ơn vì đã chỉ ra ngôn ngữ này cho tôi. Nó kết hợp những gì tôi yêu thích về cả Python và Haskell.
Kaya

@Kaya Tôi rất vui vì bạn thích nó! Trong trường hợp bạn chưa thấy, có một trang chủ tại pyos.github.io/dg và một hướng dẫn nữa! Rất nhiều hàng hóa. Và đừng ngần ngại mở một vấn đề trên kho lưu trữ nếu bạn cảm thấy như vậy. EDIT: Tôi chỉ muốn chỉ ra rằng tôi không phải là người tạo ra lang.
rubik

5

Ví dụ Ruby dựa trên Sinatra

Giải pháp dựa trên máy chủ này lưu trữ một bộ đếm cá nhân cho mỗi người dùng trong cookie.

Hãy dùng thử tại 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

Đây là một chút ngắn của perl để làm điều đó. Dữ liệu nên được lưu trữ ở đâu? Tại sao trong tập tin chương trình, tất nhiên! =)

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

Ban đầu tôi đã sử dụng tệp DATA ma thuật xử lý như vậy, nhưng tôi cảm thấy ở trên là "tinh khiết hơn":

$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

Bạn có thể lưu trữ tell DATAtrước khi bạn đọc từ nó, sau đó tìm kiếm trở lại vị trí đó.
mob

3

Bash

Kịch bản shell tự chỉnh sửa đơn giản.

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

Tôi thích giải pháp Bash của dfernig , nhưng tôi cũng muốn đăng bài của tôi:

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

Tôi nghĩ rằng giải pháp có thể được coi là khác nhau, bởi vì

  • mã thực sự được thực thi không thay đổi
  • chương trình tính toán thực tế nếu n là lũy thừa của 2

"Bộ nhớ" là kích thước tập lệnh (ban đầu là 171 byte), được tăng thêm 1 với phần bổ sung của một dòng mới ở mỗi lần thực hiện.
Quyền hạn của 2 được nhận ra bằng cách chuyển đổi kích thước chương trình (trừ 170, tất nhiên) thành nhị phân, sau đó đếm số thứ tự: nếu có chính xác một, thì n là lũy thừa của 2. Số mũ là số 0 trong số nhị phân .


1

Giải pháp Java

Uing API tùy chọn java để lưu trữ số lượng chạy; và tính toán trước các quyền hạn của 2 cho một hashmap để so sánh

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

Tôi đã chọn không sử dụng log2giải pháp rõ ràng nhưng làm việc với các toán tử bitwise để tìm vị trí bit đơn trong biểu diễn nhị phân của lũy thừa của 2 số.

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

chiến lược tuyệt vời, nhưng thật không may, các trạng thái ngắn gọn rằng nó cần hiển thị giá trị của số lần nó đã được thực hiện, được hiển thị tương ứng ... Của bạn chỉ là một forvòng lặp từ 1 đến 130, với kết xuất ...: /
WallyWest

@WallyWest, yeah, cảm ơn vì đã chỉ ra điều này.
Michael M.

Không có ý định xúc phạm ...
WallyWest

1
Tôi đã không nhận xét của bạn là một hành vi phạm tội, đó là một lời cảm ơn thực sự! Xin lỗi nếu từ của tôi không được chọn tốt, tiếng Anh không phải là tiếng mẹ đẻ của tôi.
Michael M.

1

Hồng ngọc

Được rồi, tôi nghĩ tôi sẽ thử nó ngay bây giờ. Nó tự tìm kiếm định nghĩa của 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)

(đã thử nghiệm trong Ruby 1.9.3)


1

Pháo đài 77

Mã số:

      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

Kết quả:

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

Điều này đếm số lần chạy được thực hiện trong một thư mục cụ thể. Cải thiện có thể là yêu cầu một tệp trong thư mục / tmp và thêm một semaphore để nhiều trường hợp không cố cập nhật bộ đếm cùng một lúc.
Glenn Randers-Pehrson

1

C

Một trong những cách "thích hợp" để làm điều đó (không sử dụng tệp, đó là).

Bạn có thể đưa nó resetvào dòng lệnh để đặt nó về 0. Bạn cũng có thể di chuyển hoặc sao chép thực thi xung quanh. Di chuyển thực thi đặt lại nó, và nhiều bản sao của thực thi là độc lập.

#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

Lấp lánh, 423 ký tự (chưa có mã tự sửa đổi khác). Lưu nó count.spnsau đó chạy 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

Đây là một giải pháp Python 3 nhanh, sử dụng tệp dữ liệu để lưu trữ nxgiữa các lần chạy:

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

Đầu ra của việc chạy nó 16 lần:

2^0
2^1
3
2^2
5
6
7
2^3
9
10
11
12
13
14
15
2^4

0

Con trăn 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 ;
}

Tuy nhiên, điều này yêu cầu bạn xác định một thuộc tính cài đặt trong dự án Visual Studio của bạn:

dự án chụp màn hình


0

C / POSIX

Chương trình này sử dụng số lượng liên kết cứng để thực thi riêng của nó như là bộ đếm tần suất được gọi. Nó tạo ra các liên kết cứng mới trong thư mục mà nó được bắt đầu (vì theo cách đó nó được đảm bảo nằm trên cùng một hệ thống tệp), do đó cần có sự cho phép ghi. Tôi đã bỏ qua xử lý lỗi.

Bạn nên đảm bảo rằng bạn không có tệp quan trọng nào có cùng tên với một trong những liên kết cứng được tạo trên thư mục đó, nếu không nó sẽ bị ghi đè. Nếu ví dụ: tệp thực thi được đặt tên counter, các liên kết cứng sẽ được đặt tên counter_1, counter_2v.v.

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

Chạy ví dụ (dòng đầu tiên đặt lại bộ đếm, trong trường hợp tệp thực thi đã được chạy):

$ 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

Pháo đài 95

Một tệp có tên "a" (không có phần mở rộng) theo dõi quá trình chạy chương trình.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.