Каждые 2 ^ n раз


10

Позвольте nбыть количество раз, когда ваша программа была выполнена. Если nесть сила 2, а затем распечатать , 2^xгде n = 2^x; в противном случае просто выведите число. Пример выполнения:

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

и так далее. Это конкурс популярности, поэтому ответ с наибольшим количеством голосов выигрывает ..


3
почему он выводится 0при первом запуске?
Мниип

Вы имели в виду «где n = 2^x?» Иначе во второй раз будет выходной 2^4, в четвертый раз 2^16и т. д.
Джон Дворжак

@mniip обе опечатки. Я, наверное, должен был прочитать это более внимательно ...: P
Jwosty

4
Ммм ... 1это сила двух. 2^0=1
Джон Дворжак

1
Вы все еще говорите, x = 2^xа неn = 2^x
Джон Дворжак

Ответы:


8

Java - злоупотребление API

Есть много компьютеров в сети, которые могут сосчитать, так зачем хранить счет сам?

Полное злоупотребление API стека, чтобы получить квоту и оставшуюся квоту, чтобы увидеть, сколько раз она была запущена сегодня:

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

Очевидно, что это работает только с новой суточной квотой для вашего IP, и только до квоты. Если вам нужна поддержка больших номеров, опубликуйте [feature-request], чтобы повысить quota_maxдо MAX_INT.


6

JavaScript

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

Последовательные предупреждения следующие:

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

Спасибо, любезно ... 'Это единственный способ отслеживать выполнение в JavaScript ... Я подумываю использовать localStorage для будущей игры JS ...
WallyWest

Для чего-то такого маленького, как счетчик, cookie также должен работать.
celtschk

@celtschk Отличная идея, но я считаю, что создание cookie заняло бы больше байтов
WallyWest

6

C - запись в исполняемый файл

Этот код C обновляет строку dataв исполняемом файле, так что по сути это самоизменяющийся код. Если вы запустите его более 9,999,999 раз, вы получите интересные вещи.

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

Она сегментация ошибки после компиляции с GCC 4.8.1-10ubuntu9: gcc test.c,./a.out 2^0 Segmentation fault (core dumped)
TimWolla

1
На Mac это работает, не пробовал Linux или Windoze. По-видимому, Linux более строг с доступом к себе.
Томсминг

6

Ява

Следующий код изменяет свой собственный файл класса, чтобы сохранить новый счетчик прогонов. Это было особенно весело, когда вы понятия не имели, как выглядит байт-код, но после бесчисленных часов поиска в Google и тестирования он наконец-то работает! :)

Демо (используя 7 в качестве начального значения для демонстрационных целей):

[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

Код:

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

дециграмм

Здесь я представляю вам портативный код! При каждом запуске #добавляется в конце, делая прогресс-бар! Кроме того, вы можете перенести код на другой компьютер и продолжить с того места, где вы были.

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 раз:

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

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

Ах, спасибо за указание этого языка мне. Он включает в себя то, что мне нравится в Python и Haskell.
Kaya

@ Кая, я рада, что тебе нравится! Если вы еще не видели, есть домашняя страница по адресу pyos.github.io/dg, а также учебник! Много товаров. И не стесняйтесь открывать вопрос в хранилище, если вам так хочется. РЕДАКТИРОВАТЬ: Я просто хотел отметить, что я не создатель языка.
Рубик

5

Пример Ruby на основе Синатры

Это серверное решение хранит персональный счетчик для каждого пользователя в файле cookie.

Попробуйте это на 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

Вот немного Perl, чтобы сделать это. Где должны храниться данные? Почему в самом файле программы, конечно же! знак равно

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

Первоначально я использовал магический дескриптор файла DATA вот так, но я чувствую, что выше "чище":

$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

Вы можете сохранить, tell DATAпрежде чем читать из него, а затем вернуться к этому месту.
моб

3

удар

Простой скрипт для самостоятельного редактирования.

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

удар

Я как dfernig «s решение Bash , но я хотел бы опубликовать мое , а также:

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

Я думаю, что решение можно считать другим, потому что

  • фактически выполненный код не изменяется
  • программа динамически вычисляет, является ли n степенью 2

«Память» - это размер скрипта (первоначально 171 байт), который увеличивается на 1 с добавлением новой строки при каждом выполнении.
Степени 2 распознаются путем преобразования размера программы (конечно, минус 170) в двоичный, а затем подсчета единиц: если есть ровно один, то n является степенью 2. Показатель степени - это число нулей в двоичном коде. ,


1

Решение Java

Использование API предпочтений Java для хранения суммы пробега; и предварительно рассчитал степени 2 для хэш-карты для сравнения

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

Я решил не использовать очевидное log2решение, а работать с побитовыми операторами, чтобы найти позицию одного бита в двоичном представлении степени 2 чисел.

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

отличная стратегия, но, к сожалению, в сводке говорится, что необходимо отобразить значение числа раз, которое оно было выполнено, отрисовано соответственно ... Ваш forцикл представляет собой цикл от 1 до 130 с отображением ...: /
WallyWest

@WallyWest, да, спасибо, что указал на это.
Майкл М.

Не в обиду ...
WallyWest

1
Я не воспринял ваш комментарий как оскорбление, это было большое спасибо! Извините, если мои слова выбраны неправильно, английский не мой родной язык.
Майкл М.

1

Рубин

Хорошо, я думаю, что попробую это сейчас. Он ищет себя для определения 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)


1

Фортран 77

Код:

      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

Результат:

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

Это подсчитывает количество прогонов, выполненных в определенном каталоге. Возможным улучшением будет запрос файла в каталоге / tmp и добавление семафора, чтобы несколько экземпляров не пытались обновить счетчик одновременно.
Гленн Рандерс-Персон

1

С

Один из «правильных» способов сделать это (без использования файлов).

Вы можете resetуказать его в командной строке, чтобы обнулить его. Вы также можете перемещать или копировать исполняемый файл. Перемещение исполняемого файла сбрасывает его, и несколько копий исполняемого файла являются независимыми.

#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

Сверкающий, 423 символа (еще один самоизменяющийся код). Сохраните его, count.spnзатем запустите 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

Вот быстрое решение Python 3, которое использует файл данных для хранения nи xмежду запусками:

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 раз:

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

Это, однако, требует, чтобы вы определили свойство settings в вашем проекте Visual Studio:

снимок экрана с настройками проекта


0

С / POSIX

Эта программа использует количество жестких ссылок на свой собственный исполняемый файл в качестве счетчика того, как часто он вызывался. Он создает новые жесткие ссылки в каталоге, из которого он был запущен (потому что таким образом он гарантированно находится в той же файловой системе), что, следовательно, требует разрешения на запись. Я опустил обработку ошибок.

Вам лучше убедиться, что у вас нет важного файла с таким же именем, как у одной из созданных жестких ссылок в этом каталоге, иначе он будет перезаписан. Если , например , исполняемый файл называется counter, жесткие ссылки будут названы counter_1, и counter_2т.д.

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

Пример выполнения (первая строка сбрасывает счетчик, если исполняемый файл уже запущен):

$ 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

Фортран 95

Файл с именем «a» (без расширения) отслеживает запуск программы.

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.