Jump to content

Interesting programming challenge


Lex

Recommended Posts

Hi again guys !

I've read on a website this following programming challenge ( for a job interview ) :

-you are supposed to write an application which should display a string ( whatever you want , say "string 1" ) the first time it's being ran , and a different  string ( say "string 2") if you run it again . However , you are not allowed to create write to additional files , or to the registry .

I've solved this challenge in perl using the following code :

use Tie::File;

tie my @array,'Tie::File',$0 || die "Tie errorn";

my $tmf;
chomp($tmf=<DATA>);
if($tmf eq "string1") {
    print "First runn";
    for(my $i=0;$i<$#array+1;$i++) {
    if($array[$i] eq "string1") {
        ($array[$i],$array[$i+1])=($array[$i+1],$array[$i]);
        last;
    }
}
untie @array;
}
else {
    print "Not first runn";
}
    

__DATA__
string1
string2

The code runs on any platform that supports  perl .

I tried to solve it in C too , but I've only got it to work under Linux ( the way I did it was using exec , replacing the current process image with another image that writes data in the file ) ... but on Windows the C code crashes .

I would love to see another solutions for this challenge .

Cheers !

Link to comment
Share on other sites

I had to look this over a couple of times before I got the idea.

What you're asked to do is to rewrite the program from within the program, as the program itself is the only file on the system that you're allowed to edit.

In C I think the best way to do it is to put the string to replace in a global constant. You first print out that constant, and then do a replace on the file contents for the string with a new version of that string. Note that the new string must be the same length as the original.

There might be other ways to do it, but I reckon that unless you want to figure out how each compiler puts together its local binary, it's not worth the effort.

Link to comment
Share on other sites

I get that the idea is to have the program output a string of your choice every time the program is run but the string must be unique?

I would solve this by, outputting the epochs timestamp, then sleeping for 1 second.  The output would be unique everytime, because the sleep stops the person running the program quickly.  That's the hackers way :D

Link to comment
Share on other sites

Tom , the first time you run the program , it should display a string , and after that , it doesn't matter how many times you run it again , it will display a second string ... kinda like the app knows if it's the first time being ran or not .

Link to comment
Share on other sites

Hey,

I know theres a way to do it in C#, but haven't looked into it enough.

Theres a way of adding global variables within the application that are embedded within the compiled executable.

So it will read the variables containing the 2 string values and the number of times the program has been open.  At first the program would read the first string, and obviously when the count reaches 2, it would display the second string.


mexxus

Link to comment
Share on other sites

Hey,

I did some searching in msdn, and have found out how to do it.

It doesn't seem to use any external sources to store data, but not entirely sure.

The only problem is... I have attached a reset button, but it only resets the second time you open the program after clicking reset...strange.

Hmmmm...how to upload?

I'll start work on a ftp server etc etc.

go to http://www.nuckingfoobs.com/files (doesn't exist at the moment, but will purchase soon and host domain)

The file will be variable_container.zip or similar.


mexxus

Link to comment
Share on other sites

I think this is what you ment. "you are not allowed to create write to additionalfiles , or to the registry . But you can write to yourself (the program) right? Thats not breaking the rules is it? A program that re-programs itself. If its not breaking the rules, then here is a solution in php.

hak5.php

<?php
$cent = "false";
    
    if($cent == "false")
    {
      echo "string 1";
        $lines = file('hak5.php');

            $myFile = "hak5.php";
            $fh = fopen($myFile, 'w') or die("can't open file");
            $i = 0;


        foreach ($lines as $line)
        {
              $i += 1; 
        }
        
        $lines[1] = '$cent = "true";';    
    
            
            for ( $counter = 0; $counter <= $i; $counter +=1) 
            {
                fwrite($fh, $lines[$counter]);
        
            }            

}    
    
    if($cent == "true")
    {
    
        echo "string 2";
        // two coins add up too 21cent
        // one of them isn't 1cent
        // thats what this challenge reminds me of! :)

        // sorry for the bad code - im sure it can be done in alot less lines.
    }
    

?>

After this is executed, it will never return to display "string 1", as the second line in the code has been changed to 'true'. It can only revert back to "string 1" is someone opens the source up with a text editor and changes it back.

Link to comment
Share on other sites

  • 3 weeks later...

Hypothetically, couldn't one hard-code the approximate size of the application into the application, and have it add some empty bits to the end of it after it's first run.  It could check it's own size and display a different output if it finds itself significantly bloated.  Just a similar but different means.

Link to comment
Share on other sites

I tried it with a little C program, but (at least under Linux) you can't open your own binary from within your program. The open(2) call fails when the flag is O_WRONLY, saying that the file is busy (ETXTBSY). You can cheat though:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

const char *txt1 = "A certain text.";
const char *txt2 = "A similar text.";

static void die(char *reason) {
    printf("%sn",reason);
    exit(-1);
}

static off_t get_file_size(const char *filename) {
    struct stat file_stat;

    if (stat(filename, &file_stat) != 0) {
        die("Error statting file, and too lazy to write a real error.");
    }

    return file_stat.st_size;
}

static void replace_in_buffer(const char *old,const char *new,char *buffer,off_t buffer_size) {
    size_t old_len = strlen(old);
    char *cur_pos = buffer;
    char *end_pos = buffer + buffer_size - old_len;
    while (cur_pos < end_pos) {
        if (memcmp(old,cur_pos,old_len) == 0) {
            memcpy(cur_pos,new,old_len);
            printf("Buffer patched.n");
            break;
        }
        cur_pos++;
    }
    return;
}

static void read_file_contents(const char *filename, char *buffer,off_t buffer_size) {
    int fd;
    if ( (fd = open(filename,O_RDONLY)) < 0) {
        die("Unable to open called binary for read access.");
    }
    if (read(fd,buffer,buffer_size) != buffer_size) {
        die("Amount of bytes read less than expected.");
    }
    close(fd);
}

static void write_file_contents(const char *filename,char *buffer, off_t buffer_size) {
    int fd;
    if (unlink(filename) != 0) { /* Yup, this is cheating. */
        die("Unable to remove the original program.");
    }
    if ( (fd = open(filename,O_CREAT|O_WRONLY)) < 0) {
        die("Unable to open called binary for write access.");
    }
    if (write(fd,buffer,buffer_size) != buffer_size) {
        die("Amount of bytes written less than expected - expect a corrupt binary.");
    }
    close(fd);
}

int main(int argc, char *argv[]) {
    const char *filename = argv[0];
    off_t filesize;
    char *buffer;

    filesize = get_file_size(filename);
    if ( (buffer = malloc(filesize)) == NULL) {
        die("Unable to allocate memory buffer.");
    }
    read_file_contents(filename,buffer,filesize);
    replace_in_buffer(txt1,txt2,buffer,filesize);
    write_file_contents(filename,buffer,filesize);
    free(buffer);
    printf("Text1: %snText2: %sn",txt1,txt2);
    return 0;
}

Um. Suffice to say that this works because the two strings are of equal length. I'm pretty sure if they weren't, Bad Things would happen.

Link to comment
Share on other sites

Heres my way in python.

you are not allowed to create write to ADDITIONAL files

ok, just write to the app file. might not be able to do this in those silly need-to-compile languages.

#!/usr/bin/python

string1 = "this is the first string"
string2 = "this is the second stirng"

run = 1

if run == 1:
        print string1
elif run == 2:
        print string2

f=open('app.py', 'r+') # open self, if self named app.py
f.seek(101) # go to the (run = 1) line
f.write('2') # write 2 over the 1

Link to comment
Share on other sites

I'd like to see this done using a compiled language, instead of an interpreted one.

I second that. Although my code in php wasn't cheating, doing it with a compiled language would be alot more impressive.

Just to show it can be done.

/me waits for TomB
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...