Every 2^n times

10

1

Let n be the number of times your program has been executed. If n is a power of 2, then print 2^x where n = 2^x; otherwise, simply output the number. Example run:

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

and so on. This is a popularity contest, so the answer with the most upvotes wins..

Jwosty

Posted 2014-03-04T05:01:02.720

Reputation: 3 530

3why does it output 0 in the first run? – mniip – 2014-03-04T05:19:11.123

did you mean "where n = 2^x? Otherwise the second time the output would be 2^4, the fourth time 2^16 and so on. – John Dvorak – 2014-03-04T05:23:58.707

@mniip both typos. I probably should've read that more carefully... :P – Jwosty – 2014-03-04T05:27:08.040

4Umm... 1 is a power of two. 2^0=1 – John Dvorak – 2014-03-04T05:32:09.973

@JanDvorak Uggh, you're right. – Jwosty – 2014-03-04T05:32:38.450

1You still say x = 2^x rather than n = 2^x – John Dvorak – 2014-03-04T05:36:22.353

Is there any rule about how we count the number of times we've been run? I've just posted an answer that uses an external data file, but as I was finishing it it occurred to me that you might have wanted us to be modifying our own source code instead (which would only be a little bit harder). – Blckknght – 2014-03-04T06:13:31.033

@Blckknght I thought about doing that, but people will up vote the more creative one more. – Jwosty – 2014-03-04T14:09:50.883

Answers

8

Java - API Abuse

There are plenty of computers online that can count, so why store the count myself?

Full-on abuse of the Stack API to get quota and remaining quota to see how many times it's been run today:

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

Obviously this only works with a fresh daily quota for your IP, and only up to the quota. If you want support for higher numbers, post a [feature-request] to raise quota_max to MAX_INT.

Geobits

Posted 2014-03-04T05:01:02.720

Reputation: 19 061

6

JavaScript

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

Successive alerts are as follows:

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

WallyWest

Posted 2014-03-04T05:01:02.720

Reputation: 6 949

Thank you kindly... 'Twas the only way to keep track of executions in JavaScript... I'm considering using localStorage for an upcoming JS game... – WallyWest – 2014-03-04T22:27:59.290

For something as small as a counter, a cookie should work as well. – celtschk – 2014-03-06T22:23:47.877

@celtschk Great idea, but I believe making a cookie would have taken more bytes – WallyWest – 2014-12-04T22:47:45.847

6

C – writing to the executable

This C code updates the string data in the executable, so essentially this is self-modifying code. If you run it over 9,999,999 times, you get interesting stuff.

#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

Posted 2014-03-04T05:01:02.720

Reputation: 2 034

It Segmentation faults after compiling it with GCC 4.8.1-10ubuntu9: gcc test.c, ./a.out 2^0 Segmentation fault (core dumped) – TimWolla – 2014-03-04T16:40:54.093

1On Mac it works, haven't tried Linux or Windoze. Apparently Linux is more strict with accessing yourself. – tomsmeding – 2014-03-04T20:32:45.590

6

Java

The following code modifies it's own class file to store the new run count. This was especially fun when you had no idea how the byte code looks, but after countless hours of Googling and Testing it finally works! :)

Demo (using 7 as starting value for demo purposes):

[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

Posted 2014-03-04T05:01:02.720

Reputation: 1 878

5

perl

Here's a short bit of perl to do it. Where should the data be stored? Why in the program file itself, of course! =)

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

Originally I had used the magic DATA file handle like so, but I feel the above is "purer":

$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

Posted 2014-03-04T05:01:02.720

Reputation: 1 197

You can store tell DATA before you read from it, then seek back to that spot. – mob – 2014-03-10T21:23:20.297

5

Sinatra-based Ruby Example

This server-based solution stores a personal counter for each user in a cookie.

Try it at 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

Posted 2014-03-04T05:01:02.720

Reputation: 151

5

dg

Here I present you a portable code! At every run a # is added at the end, making a progress bar! Also, you can move the code to another machine and resume from where you were.

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

#

After 18 times:

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

Posted 2014-03-04T05:01:02.720

Reputation: 222

Ahh, thanks for pointing this language out to me. It incorporates what I love about both Python and Haskell. – Kaya – 2014-03-04T17:35:17.267

@Kaya I'm happy you like it! In case you haven't already seen, there's a homepage at https://pyos.github.io/dg and a tutorial as well! Lots of goods. And don't hesitate to open an issue on the repository if you feel like so. EDIT: I just wanted to point out that I am not the creator of the lang.

– rubik – 2014-03-04T18:14:46.847

3

Bash

Simple self-editing shell script.

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

Posted 2014-03-04T05:01:02.720

Reputation: 191

2

Bash

I like dfernig's Bash solution, but I would like to post mine as well:

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

I think the solution can be considered different, because

  • the code actually executed doesn't change
  • the program dinamically calculates if n is a power of 2

The "memory" is the script size (initially 171 bytes), which is increased by 1 with the append of a newline at each execution.
Powers of 2 are recognized by converting the program size (minus 170, of course) to binary, and then counting the ones: if there is exactly one one, then n is a power of 2. The exponent is the number of zeros in binary.

scristalli

Posted 2014-03-04T05:01:02.720

Reputation: 121

1

Javascript

I chose to not use the obvious log2 solution but work with bitwise operators to find the single bit position in the binary representation of power of 2 numbers.

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.

Posted 2014-03-04T05:01:02.720

Reputation: 12 173

great strategy, but unfortunately, the brief states that it needs to display the value of the number of times it has been executed, rendered accordingly... Yours is just a for loop from 1 to 130, with the rendering... :/ – WallyWest – 2014-03-04T12:04:12.233

@WallyWest, yeah, thanks for pointing this out. – Michael M. – 2014-03-04T12:21:49.270

No offence intended... – WallyWest – 2014-03-04T12:36:11.087

1I had not taken your comment as an offense, that was a real thanks ! Sorry if my words are not well chosen, english is not my mother tongue. – Michael M. – 2014-03-04T13:29:17.197

1

Java solution

Uing the java preferences API to store the run amount; and precalculated the powers of 2 for a hashmap to compare

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

Posted 2014-03-04T05:01:02.720

Reputation: 3 942

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

Result:

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

Posted 2014-03-04T05:01:02.720

Reputation: 1 877

This counts the number of runs done within a particular directory. Possible improvement would be to request a file in the /tmp directory, and to add a semaphore so multiple instances don't try to update the counter at the same time. – Glenn Randers-Pehrson – 2014-03-04T22:29:28.403

1

Ruby

Alright, I think I'll try this now. It searches itself for the definition of 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)

(tested in Ruby 1.9.3)

Jwosty

Posted 2014-03-04T05:01:02.720

Reputation: 3 530

1

C

One of the "proper" ways to do it (without using files, that is).

You can give it reset on the command line to set it back to zero. You can also move or copy the executable around. Moving the executable resets it, and multiple copies of the executable are independent.

#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

Posted 2014-03-04T05:01:02.720

Reputation: 30 224

1

Sparkling, 423 characters (yet another self-modifying code). Save it as count.spn then run 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

Posted 2014-03-04T05:01:02.720

Reputation: 241

0

Here's a quick Python 3 solution, which uses a data file to store n and x between runs:

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

The output of running it 16 times:

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

Blckknght

Posted 2014-03-04T05:01:02.720

Reputation: 701

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

Posted 2014-03-04T05:01:02.720

Reputation: 111

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

This does, though, require that you define a settings property in your Visual Studio project:

project settings screen shot

Nicholas Carey

Posted 2014-03-04T05:01:02.720

Reputation: 41

0

C/POSIX

This program uses the number of hard links to its own executable as counter of how often it was called. It creates the new hard links in the directory it was started from (because that way it's guaranteed to be on the same file system), which therefore needs write permission. I've omitted error handling.

You better make sure that you have no important file with the same name as one of the created hard links on that directory, or it will be overwritten. If e.g. the executable is named counter, the hard links will be named counter_1, counter_2 etc.

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

Example run (the first line resets the counter, in case the executable has already been run):

$ 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

Posted 2014-03-04T05:01:02.720

Reputation: 4 650

0

Fortran 95

A file named "a" (without extension) keeps track of the run of the program.

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

Posted 2014-03-04T05:01:02.720

Reputation: 494