TumblrFeed

Curate, connect, and discover

~ath - Blog Posts

5 months ago

Two questions: 1: did you actually make ~ATH, and 2: what was that Sburb text-game that you mentioned on an ask on another blog

While I was back in highschool (iirc?) I made a thing which I titled “drocta ~ATH”, which is a programming language with the design goals of:

1: being actually possible to implement, (and therefore, for example, not having things be tied to the lifespans of external things)

2: being Turing complete, and accept user input and produce output for the user to read, such that in principle one could write useful programs in it (though it is not meant to be practical to do so).

3: matching how ~ATH is depicted in the comic, as closely as I can, with as little as possible that I don’t have some justification for based on what is shown in the comic (plus the navigation page for the comic, which depicts a “SPLIT” command). For example, I avoid assuming that the language has any built-in concept of numbers, because the comic doesn’t depict any, and I don’t need to assume it does, provided I make some reasonable assumptions about what BIFURCATE (and SPLIT) do, and also assume that the BIFURCATE command can also be done in reverse.

However, I try to always make a distinction between “drocta ~ATH”, which is a real thing I made, and “~ATH”, which is a fictional programming language in which it is possible to write programs that e.g. wait until the author’s death and the run some code, or implement some sort of curse that involves the circumstantial simultaneous death of two universes.

In addition, please be aware that the code quality of my interpreter for drocta ~ATH, is very bad! It does not use a proper parser or the like, and, iirc (it has probably been around a decade since I made any serious edits to the code, so I might recall wrong), it uses the actual line numbers of the file for the control flow? (Also, iirc, the code was written for python 2.7 rather than for python 3.) At some point I started a rewrite of the interpreter (keeping the language the same, except possibly fixing bugs), but did not get very far.

If, impossibly, I got some extra time I wouldn’t otherwise have that somehow could only be used for the task of working on drocta ~ATH related stuff, I would be happy to complete that rewrite, and do it properly, but as time has gone on, it seems less likely that I will complete the rewrite.

I am pleased that all these years later, I still get the occasional message asking about drocta ~ATH, and remain happy to answer any questions about it! I enjoy that people still think the idea is interesting.

(If someone wanted to work with me to do the rewrite, that might provide me the provided motivation to do the rewrite, maybe? No promises though. I somewhat doubt that anyone would be interested in doing such a collaboration though.)

Regarding the text based SBURB game, I assume I was talking about “The Overseer Project”. It was very cool.

Thank you for your questions. I hope this answers it to your satisfaction.


Tags
3 years ago

My ~ATH keeps crashing whenever I run a non-computer exploding code, or if I press enter. Why is this?

Based on the username which recently followed this blog at the same time as I received this ask (which I won't say what it was because you asked this on anon, and haven't received permission), I'd guess that you may be running a different version of ~ATH than the one I document here :P

Unfortunately, I don't have a specification for the version you have.

If you have such a specification, or the executable for it, I'd be happy to take a look if you could send it to me, haha.

If on the off chance you are using the version I document here, then presumably you have a syntax error or something in your code?


Tags
3 years ago

yeah, can i make ~ATH continue to generate variables? like if one part of the program dies it generates another variable? because i've been trying to do that lmfao

Hi. Not sure what you mean by continue to generate variables. If you mean like how in lisp you can like, automatically generate a new variable name and then use that variable name, then no, drocta ~ATH doesn't have a feature like that, but I'm guessing that's not what you mean.

Variables are just like, names in your program. If you want more objects, you can just continue bifurcating objects to get more objects.

drocta ~ATH does not support parallelism or concurrency or whatever (though presumably canonical ~ATH would, in some sense. At least, it appears to handle circumstantial simultaneity.), So, if you are referring to drocta ~ATH, then I'm not sure what you mean when you refer to part of the program dying. Though, given that in canonical ~ATH, there is the expression

[THIS,THIS].DIE();

then it seems like, presumably, it should be possible to have something like

THIS.DIE();

in order to describe part of the program dying (ending), without another part doing so.

But, again, drocta ~ATH does not support anything like that. Feel free to make a fork of it which does though. Please let me know if you do!


Tags
11 years ago

re: "computationalalchemist answered: You could use Prolog-style lists for split."

"computationalalchemist answered: You could use Prolog-style lists for split."

I'm not totally sure what you mean, but my best guess as to what you meant is probably pretty similar to how I making it.

I implemented it and I think it works, I need to double check though.

With what I have now when I use 

split [THIS,THIS,THIS,THIS,THIS,THIS,NULL]COUNTER; ~ATH(COUNTER){ print "bananas"; BIFURCATE COUNTER[JUNK,COUNTER]; }EXECUTE(print "ok";); print "whee!";

it yields 

bananas bananas bananas bananas bananas bananas ok whee!

Which seems to make sense to me, and also, fits with how lisp lists work, and apparently also prolog lists.

also where it says split it will also accept bifurcate. they are actually treated as the same command.

import statements aren't fully implemented yet though.

I think I will put this version on github pretty soon.

Thank you for the advice.


Tags
11 years ago

Hello again all!

So recently I started kind of working on this again for a bit. I have fixed some bugs with the parser that I haven't pushed yet. I am also writing an improved interpreter that will use the parser instead of the hacky thing that just goes through strings.

However, for the time being, even after I release this version, I would recommend maybe using the older version for a while if anyone is using it, because this version is probably even more buggy.

However, you know how a few posts ago (but more than a year ago (wow) ) I posted that post where I said that I didn't think bifurcate can be used to split values into more than 2 values?

Well I still kind of think that, but on the map page for homestuck on act 6, it says split Act_6[Act_1,Act_2,Act_3,<etc>];

So this is something I intend to implement, and something I am implementing.

And like I said before I would like it to be done with repeated bifurcation, as a sort of syntactic sugar.

And I am thinking I want it to be like

[a,b,c] means the same thing as [a,[b,c]]

so split Z[A,B,C];

would be the same as

BIFURCATE Z[A,BCTEMP]; BIFURCATE BCTEMP[B,C];

and that split [A,B,C]Z;

would be the same as

BIFURCATE [B,C]BCTEMP; BIFURCATE [A,BCTEMP]Z;

But the way the splits would be done could also be backwards

so [a,b,c] could be the same as [[a,b],c]

I'm pretty sure I prefer the first way, but the second way is actually easier to implement.

or at least cleaner looking to implement.

Why doesn't my code look clean ever?

Anyway, my reason for this post is this:

Does anyone have any opinions about how split is implemented?


Tags
11 years ago

I made a parser

I made a parser for ~ATH in addition to the interpreter. I might make the interpreter use the parser at some point in the future, or I might not. If I made the interpreter use the parser, the code for the interpreter would probably be a little cleaner, and possibly a little faster.

The parser is available from my github.

To use it, call tokenize on the text, and then read_all_from on the result of tokenize.

The output will be a list of lists

https://github.com/drocta/TILDE-ATH-Parser

(haven't updated lately because of other unrelated projects, and also other reasons that aren't necessary to describe)


Tags
12 years ago

User defined functions can be used now! Also PRINT2 added!

PRINT2 prints a string object as a string. If you give it something that is not a string object it will probably crash, or output the empty string.

Now, to import user defined functions use 

importf filename as FUNCTIONNAME;

Why didn't I put this up earlier?

because I have other projects and because sometimes I am busy/lazy.

OK!

So to make a function to import, you pretty much make a ~ATH file like normal, except the object passed into the function is put into the variable ARGS, and when you want to pass the output object of the function out, you have it as an argument to the DIE method.

It can either be when saying THIS.DIE(RETURNOBJ); or ANYOTHERVARIABLE.DIE(RETURNOBJ);

The object your killing doesn't have to be the one tied to the life of the function or anything.

Oh I should clarify, the THIS variable/object will refer to the current function, not the file that called it.

It CAN be returned, and will be dead when you exit the function.

PROGRESS!

FUNCTIONS WORK.

LESS SPAGHETTI CODE.

although this starts to make me wonder if maybe this strays too far from what ~ATH is like in comic, 

but w/e.


Tags
12 years ago

I've realized that my tutorials haven't been tutorial-y enough

I've realized that recently, my tutorial posts have been too much code and not enough explanation. That was a mistake on my part, so I am going to go back now and give better explanations.

Also, I have started to make a table of contents page.

I figured that if someone wanted to read the tutorial after a significant part of it were finished, that they might have trouble, because it would kind of be in reverse order.

So TABLE OF CONTENTS AHOY!

Yeah.

So uh, any suggested changes to the format of the TOC page?

Why cant I mark this as a post that can be answered? I can let people photo reply, but once it goes in drafts I can't let people answer this question? Or is it too long?

What is with this interface?


Tags
12 years ago

ok, made some small commits...

(no features added, but cleaned up some code and added example programs)

yup.

it has the basis for how I am going to make functions if I make them, and cleaned up the code for BIFURCATEion, and removed some lines that were commented out.

if you want the new version it is on the github.

no real difference when it runs though.

(if something you wrote doesn't work with the new version, try using BIFFURCATE instead of BIFURCATE to use the old code. You probably won't need to, though. It works fine for me. and you probably haven't written anything in it anyway, because you kind of have to uh, want to, I guess)


Tags
12 years ago

planned features and feedback.

I am planning two features to add.

one us user defined functions.

the second is, uh, it would let you make an object that would have itself as one of its components or one of the component of one of its components etc.?

the third one I am not sure if I think it is dumb yet, but I was thinking maybe functions being objects that you can bifurcate together to make functions.

which would allow for macros kind of?

which of these three features are good ideas, (as in, for each, it is a good idea)?


Tags
12 years ago

I am so bad at updating. (and a side note)

I am still intending to update this.

but I am not good at time management.

I have like 2 hours of free time after school, (because of certain inefficiencies on my part) so that's my stupid excuse.

I am working on writing some responses to some requests for clarification, and then I will do the second part of the converter TO binary.

the print command can have the end of a loop in.

The contents of the print command can be executed.

so if you say:

import blah A; import bleh B; ~ATH(A){ ~ATH(B){ print heh } ~ATH(NULL){ print giant frogs alert; B.DIE(); } }  

it should print

"heh } ~ATH(NULL){ print giant frogs alert giant frogs alert"

this of course, is not particularly useful as far as I can tell, except possibly for quines, and possibly obfuscation. but really, is it possibly to write anything in ~ATH that isn't obfuscated?

speaking of not obfuscated, I have started working on adding a feature for user defined functions. I have it pretty much worked out how it will work, but I am not sure how I want to make the user DEFINE the functions. so I haven't been doing NOTHING with regards to this.


Tags
12 years ago

unary to binary (back again, an objects journey) (part 1)

ok, so last time I didn't actually get to converting from unary to binary again.

So I guess I will do that here. (HAHA I JUST GOT IT TO DIVIDE WITH REMAINDER. APPLYING THAT TO THE CONVERSION IN PART 2)

so to do this we have to find the largest power of two not greater than the number,  then the largest power of two not greater then what is remaining of the number, and repeat until we reach zero.

OR we can

find the largest power of two not greater than the number, then for each power of two less than the number, if it is not greater than it, use a 1 and subtract it from the remaining number.

and then for both of these, of course, reverse the result at the end so it is in the right order. 

I think so far the second one of these sounds better.

but come to think of it, repeated integer division by two might work well.

that is, instead of repeated doubling, and then checking which one is larger, it might be faster to do repeated halving. (with a remained of either zero or one)

this could be then used to make a integer base 2 logarithm, with a remainder thing.

and instead of checking each power of two less than it, we could just find the integer base 2 log, and the base 2 log of the "remainder" and the base 2 log of THAT remainder and so on.

that seems like its the best way to me so far, but how do we take the integer logarithm AND get the log remainder thing?

getting the logarithm is fairly simple, just keep dividing by the number until you reach 1.

but how do you get the remainder part? and also how do you do the integer division in the first place with these number like things that we have created?

well lets answer the first of those questions first.

It seems like the remainder of the logarithm is probably related to the remainders of the divisions that make it up.

so lets look at taking the integer base 2 logarithm of 9:

9 4 (rem 1) 2 1

that took 3 halvings, and there was one remainder of one.

what if we try on 10 or something though?

10 5 2 (rem 1) 1

that also took 3 steps and one remainder, but the remainder was on a different step.

now lets try 11

11

5 (rem 1) 2 (rem 1) 1 (rem 0)

now wait, theres a pattern here, which might allow for converting it even faster.

the remainders of the divisions are the remainders of the logs expressed in binary!

we COULD turn them back into unary, so we could take the log of it again,

but what we are doing it converting it into binary anyway! (so that would be a silly step)

so if we look at what we were doing with the repeated division again, but looking at the numbers in binary, it will be pretty evident how to convert it in a better way.:

lets try 9 again (which is 1001)

1001

100 (rem 1) 10 (rem 0) 1 (rem 0) 0 (rem 1)

whats that? the remainders are the number we want in binary?

and now that I think of that it was kind of obvious?

yes. I for some reason did not think of that earlier.

so yeah, thats what we will do, we will repeatedly integer divide the number by 2 until we reach zero, and the remainders will be the number in binary.

but wait, we haven't even written out how to divide the number by two in the first place!

well turns out its not actually that hard to do.

in a loop (that keeps looping provided the number is not zero) subtract one, and if its still not zero, subtract one again. if it is zero after the first subtracting, the remainder of that division is 1. (only the last loop will cause the remainder to be 1) count the number of times where 2 was subtracted. 

so like for 5 that would be

5 3 1 1 2 0 2 (remainder 1)

so that gives the correct answer (2 with remainder zero)

ok, now to implement this integer division by 2 in drocta ~ATH (wow! already? that was fast! /sarcasm)

//given that NUM is the variable that has the name we are halving BIFURCATE [NUM,NUM]2NUM; BIFURCATE 2NUM[NUMCPY,JUNK]; BIFURCATE [BLAH,BLAH]2BLAH; BIFURCATE 2NULL[SUBCOUNT,REMAINDER]; ~ATH(NUMCPY){ BIFURCATE 2BLAH[UNEVEN,JUNK]; BIFURCATE NUMCPY[JUNK,NUMCPY]; BIFURCATE [NUMCPY,NUMCPY]2NUMCPY; BIFURCATE 2NUMCPY[NUMCPYCPY,JUNK]; ~ATH(NUMCPYCPY){ BIFURCATE [BLAH,SUBCOUNT]SUBCOUNT; BIFURCATE NUMCPY[JUNK,NUMCPY]; BIFURCATE 2NULL[UNEVEN,NUMCPYCPY]; } ~ATH(UNEVEN){ BIFURCATE [BLAH,REMAINDER]REMAINDER; BIFURCATE 2NULL[UNEVEN,JUNK]; } } BIFURCATE [NUMCPY,NUMCPY]2NUMCPY; BIFURCATE 2NUMCPY[NUMDIV2,JUNK]; 

ok, that should divide the number by 2, put the result in NUMDIV2, and put the remainder in REMAINDER.

this takes linear time based on the size of the unary number. (provided I didn't make a mistake)

so now it is time to make sure it works, hold on a second while I check it. (I mean, im not going to post this until after I check it, so it doesn't really make sense to tell you to wait, because you just keep reading, but as I am writing this, I am about to test it.)

ok, I tested it. and it didn't seem to work, but then I realized that I made a mistake in making the test. (I checked the wrong variable)

but yeah, turns out that works...

ok, so now we need to repeatedly divide the number by two to get the remainders.

and we need to store these remainders in a list or something.


Tags
12 years ago

reading binary numbers from the user, continued.

when we left off, we had code to interpret one binary number from user input, and output it as a unary number. In this post we will add the second user input, and maybe make a thing that converts from unary to binary, and then outputs it.

The code for that was the following:

import blah BLAH; print please enter whatever character you will be using for binary zero.; INPUT ZEROCHAR; BIFURCATE ZEROCHAR[ZEROCHAR,JUNK]; import chrcmp CMP0; BIFURCATE [CMP0,ZEROCHAR]D; D.DIE(); print please enter whatever character you will be using for binary one.; INPUT ONECHAR; BIFURCATE ONECHAR[ONECHAR,JUNK]; import chrcmp CMP1; BIFURCATE [CMP1,ONECHAR]D; D.DIE(); BIFURCATE [NULL,NULL]2NULL; BIFURCATE 2NULL[OUTNUM,JUNK]; print please input the binary number you want.(it will be converted to unary); INPUT BINNUM; ~ATH(BINNUM){ BIFURCATE [OUTNUM,OUTNUM]G; BIFURCATE G[NCOPY,OUTNUM]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,OUTNUM]OUTNUM; }  BIFURCATE BINNUM[CHAR,BINNUM]; BIFURCATE [CMP0,CHAR]NEQ0; ~ATH(NEQ0){ BIFURCATE [BLAH,OUTNUM]OUTNUM; BIFURCATE 2NULL[NEQ0,JUNK]; } } print ok, going to print it out in unary, with each digit on one line. If the number you entered was large you might want to close the program instead of hitting enter.; INPUT JUNK; BIFURCATE [OUTNUM,OUTNUM]GOUTNUM; BIFURCATE GOUTNUM[OUTNUMCOPY,JUNK]; ~ATH(OUTNUMCOPY){ BIFURCATE OUTNUMCOPY[JUNK,OUTNUMCOPY]; print 1; }

ok, so what do we need to do after that?

Well we need to make it get two numbers, right?

Yes. Yes we do.

But getting one number was kind of long, wasn't it.

Luckily we don't have to have the entire thing there twice, much of it we can jusst have it in there once.

we COULD define a function, but I haven't added that to the interpreter yet, so yeah...

so a significant portion of that was initialization stuff that doesn't need to be duplicated. the first 14 lines in fact!

so pretty much we just duplicate everything but the first 14 lines.

gee, now I sound lazy for not writing this part earlier.

anyway, here goes:

import blah BLAH;

print please enter whatever character you will be using for binary zero.;

INPUT ZEROCHAR;

BIFURCATE ZEROCHAR[ZEROCHAR,JUNK];

import chrcmp CMP0;

BIFURCATE [CMP0,ZEROCHAR]D;

D.DIE();

print please enter whatever character you will be using for binary one.;

INPUT ONECHAR;

BIFURCATE ONECHAR[ONECHAR,JUNK];

import chrcmp CMP1;

BIFURCATE [CMP1,ONECHAR]D;

D.DIE();

BIFURCATE [NULL,NULL]2NULL;

BIFURCATE 2NULL[OUTNUM,JUNK];

print please input the first binary number you want.(it will be converted to unary);

INPUT BINNUM;

~ATH(BINNUM){

BIFURCATE [OUTNUM,OUTNUM]G;

BIFURCATE G[NCOPY,OUTNUM];

~ATH(NCOPY){

BIFURCATE NCOPY[JUNK,NCOPY];

BIFURCATE [BLAH,OUTNUM]OUTNUM;

BIFURCATE BINNUM[CHAR,BINNUM];

BIFURCATE [CMP0,CHAR]NEQ0;

~ATH(NEQ0){

BIFURCATE [BLAH,OUTNUM]OUTNUM;

BIFURCATE 2NULL[NEQ0,JUNK];

}

}

BIFURCATE [BLAH,OUTNUM]UINNUM1;

BIFURCATE UINNUM1[JUNK,UINNUM1];

BIFURCATE 2NULL[OUTNUM,JUNK];

print input the second binary number:;

INPUT BINNUM;

~ATH(BINNUM){

BIFURCATE [OUTNUM,OUTNUM]G;

BIFURCATE G[NCOPY,OUTNUM];

~ATH(NCOPY){

BIFURCATE NCOPY[JUNK,NCOPY];

BIFURCATE [BLAH,OUTNUM]OUTNUM;

BIFURCATE BINNUM[CHAR,BINNUM];

BIFURCATE [CMP0,CHAR]NEQ0;

~ATH(NEQ0){

BIFURCATE [BLAH,OUTNUM]OUTNUM;

BIFURCATE 2NULL[NEQ0,JUNK];

}

}

BIFURCATE [BLAH,OUTNUM]UINNUM2;

BIFURCATE UINNUM2[JUNK,UINNUM2];

BIFURCATE [UINNUM1,UINNUM1]CUINNUM1;

BIFURCATE CUINNUM1[SUM,JUNK];//haha, some junk

BIFURCATE [UINNUM2,UINNUM2]CUINNUM2;

BIFURCATE CUINNUM2[UINNUM2CPY,JUNK];

~ATH(UINNUM2CPY){

BIFURCATE UINNUM2CPY[JUNK,UINNUM2CPY];

BIFURCATE [BLAH,SUM]SUM;

}

print ok, going to print the sum out in unary, with each digit on one line. If the numbers you entered were large you might want to close the program instead of hitting enter.;

INPUT JUNK;

BIFURCATE [SUM,SUM]GSUM;

BIFURCATE GSUM[SUMCOPY,JUNK];

~ATH(SUMCOPY){

BIFURCATE SUMCOPY[JUNK,SUMCOPY];

print 1;

}

ok. That worked. I haven't made it convert the output to binary yet. I started this the day of the other post, but there was a bug I didnt get around to fixing in it that I didn't find the fix for until today.

that bug was that in the part where it changes the binary number to a unary number, the first time around, the unary number starts at zero and increases to what it should be...

...but I forgot to include the line to reset it back to zero for the second number.

but in works now.

I might make the part where it converts from unary to binary now instead of later, but I have to do stuff.

Sorry for having such a slow post rate, it is partly because I am busy and partly because I am lazy. mostly the [FORMER,LATTER].

hey, it adds the numbers that were entered in binary...

So a future improvement is to make it so it outputs it in binary as well.

Another possible future post is something that shouldn't work but the interpreter has a certain bug that might be amusing, and will not negatively affect many things.

specifically, if you have a "}" inside of a print statement, and you are jumping to the end of a loop, it will jump to the inside of the print statement, and execute the text as code. This is a bug, not a feature, so you should not rely on it when writing stuff. It might be fun to mess with though.

I might add user defined functions to the interpreter soon...

I don't feel that this post really explained much of anything, but I have to do stuff now, so I am going to post this, and possibly modify it later with clarifications.

Feel free to send me messages asking about how some part works.


Tags
12 years ago

reading the contents of user input, and calculator improvement

This post will cover how to actually determine WHAT the user has typed, instead of just how long it is. It will also include how to interpret what the user enters as a binary number, so that its easier to type.

An Essential part of making it interpret binary numbers is making it double numbers repeatedly.

This actually has a few ways that can be done, so this is one of the first situations where coding style for this problem might differ from person to person. Because of this, I will say more than one way to do it.

The first way to do this it to copy the number twice, and then start from zero and add both of the copies. This is relatively inefficient, and would take

a copy thing, consisting of two bifurcates (which would take a little time)

where the size of the initial number is N, 2N normal bifurcates, 2N reverse bifurcates, and 4N lines relating to the actual loop

assuming each command takes the same amount of time (which is an oversimplification) this would take 9N+C line times. (C is a constant) This might be acceptable, but there is a more efficient and nicer looking way.

The second way is nicer looking, but still not the most effecient. However, when multiplying by a larger number(such as 3, or 4, or even large numbers), this method is part of what would be used.

The second method is essentially copying the number (using a reverse bifurcate and a normal bifurcate), and then adding the number to zero, except instead of each loop increasing the new number by one, it increases it by two. This is shorter, and it looks nicer. It also only takes half as many normal bifurcates. As a result, the number of steps it would take (again assuming each step is the same length) is 8N+C, instead of 9N+C 

this one I will write out, but it is still not the best way:

//N is the number initially BIFURCATE [NULL,NULL]2NULL; BIFURCATE [N,N]G; BIFURCATE G[NCOPY,JUNK]; BIFURCATE 2NULL[RESULT,JUNK]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,RESULT]RESULT; BIFURCATE [BLAH,RESULT]RESULT; } 

ok, so yeah. that takes N, and puts twice N into RESULT, but it is still inefficient.

A more efficient version is to copy the initial number, and add the number to itself. This way you only have to do half the number of reverse BIFURCATE statements. This is much more efficient, taking instead the steps:

a copy thing, consisting of two bifurcates (which would take a little time)

where the size of the initial number is N, N normal bifurcates, N reverse bifurcates, and 2N lines relating to the actual loop

This has 7N+C steps, which is a significant improvement. I think it is the fastest way to double a number in drocta ~ATH.

It is as follows (N is the number)

BIFURCATE [N,N]G; BIFURCATE G[NCOPY,RESULT]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,RESULT]RESULT; } 

This is shortest and fastest solution I have found. If you find a shorter or faster method, please tell me.

Ok. Now we can double numbers. That is good. That is an important step. But we still haven't gotten user input to be read in any reasonable way.

Hang on, I'm GETTING TO THAT. GEEZ. (I'm kidding, no one has been complaining about my taking so long, other than myself)

Ok, so here goes:

To interpret the binary number input and convert it to a "number", we can follow the following algorithm:

start with zero.(this is before the loop)

If there are any characters left, double the number that is being created.

remove the first character from the remaining characters. If it is "1" or whatever symbol (or alternatively if it is not "0"), add one to the number that is being created. Otherwise, continue onto step 4 without doing anything first.

go back to the start of the loop (step 2)

Ok. thats the algorithm we are going to use. But I STILL haven't explained how to recognize what the next character is. Seriously what is up with that?

What you do is you bifurcate the rest of the input into [the next character,the rest of the input].

Now you have the next character. Then what you do is you reverse bifurcate it with some other object, and then you check whether that object is already dead or not.

But how do you make it so the combination is already dead? How do you get the object for the character before the user has even inputed it?

Answer: You don't. Not in the current version of drocta ~ATH anyway. You will have to tell the user to enter all the characters they will be using ahead of time. Yes this is horrible and stupid. No its not exactly like that in the comic. Its ~ATH what do you expect? :P

that might change in future versions, but I will try to stay backwards compatible with that.

but anyway, back to comparing it:

so you say something along the lines of:

import comparingobject CMP1; othercodehere makeNEQ1besomethingalive BIFURCATE [CMP1,CHAR]EQ1; BIFURCATE [NULL,NULL]2NULL; ~ATH(EQ1){ print yep, they are equal; BIFURCATE 2NULL[EQ1,NEQ1]; } ~ATH(NEQ1){ print nope, they are not equal; BIFURCATE 2NULL[NEQ1,JUNK]; }  

in the othercodehere you get the character a head of time, and say BIFURCATE[CMP1,THECHARTHATMATCHESWITHCMP1]D; D.DIE();

That makes it so that it will go through the one section of code if the character is the right one, but something else if it is something else.

Which is what we want.

So to put it all together, and make the thing that interprets the input as a binary number(hold on tight(ok, what, why did I say that), this will be a long one(why am I talking like this?)):

import blah BLAH; print please enter whatever character you will be using for binary zero.; INPUT ZEROCHAR; BIFURCATE ZEROCHAR[ZEROCHAR,JUNK]; import chrcmp CMP0; BIFURCATE [CMP0,ZEROCHAR]D; D.DIE(); print please enter whatever character you will be using for binary one.; INPUT ONECHAR; BIFURCATE ONECHAR[ONECHAR,JUNK]; import chrcmp CMP1; BIFURCATE [CMP1,ONECHAR]D; D.DIE(); BIFURCATE [NULL,NULL]2NULL; BIFURCATE 2NULL[OUTNUM,JUNK]; print please input the binary number you want.(it will be converted to unary); INPUT BINNUM; ~ATH(BINNUM){ BIFURCATE [OUTNUM,OUTNUM]G; BIFURCATE G[NCOPY,OUTNUM]; ~ATH(NCOPY){ BIFURCATE NCOPY[JUNK,NCOPY]; BIFURCATE [BLAH,OUTNUM]OUTNUM; }  BIFURCATE BINNUM[CHAR,BINNUM]; BIFURCATE [CMP0,CHAR]NEQ0; ~ATH(NEQ0){ BIFURCATE [BLAH,OUTNUM]OUTNUM; BIFURCATE 2NULL[NEQ0,JUNK]; } } print ok, going to print it out in unary, with each digit on one line. If the number you entered was large you might want to close the program instead of hitting enter.; INPUT JUNK; BIFURCATE [OUTNUM,OUTNUM]GOUTNUM; BIFURCATE GOUTNUM[OUTNUMCOPY,JUNK]; ~ATH(OUTNUMCOPY){ BIFURCATE OUTNUMCOPY[JUNK,OUTNUMCOPY]; print 1; } print Am I a terrible person for writing this?; 

Oh gosh. I wish I could indent in tumblr. that is terrible to read. tumblr is a terrible source code editor.

One time someone called me a masochaist for writing this type of stuff.

And then we just have to put that together with the adding thing, and then maybe add a better way of outputting the number. maybe in binary.

HAHAHAHAH

ok, yeah, I'm going to put it together in the next post, not this one, because I have to homework now.(using the noun homework as a verb was intentional)

yeah. putting it together in the next post.

As always, if something was confusing, please ask for clarification.


Tags
12 years ago

User input, and a basic calculator.

Most programs people use have some form of user input. A calculator isn't much use if it always uses the same numbers after all!

~ATH of course accepts user input and output as shown in the file Roxy sent Jane.

Also I just found out you can put more than one read more line in one post.

The input command has the syntax:

INPUT VARNAME;

What this does is when program execution meets this line, the program pauses execution, allowing the user to input text. When the user hits enter, program execution will continue and the variable VARNAME will be made to point to an object corresponding to the text the user entered.

This object is such that the left half is the object that corresponds to the first character. If there is no character after that, the right half will be the NULL object. Otherwise the right half will be the object corresponding to the input without the first character. If they hit enter without inputting any characters the object will just be the NULL object.

Now that we have that all explained, we can start to make programs that actually take user input!

As you might have guessed from the title, the thing we will be making is a very basic calculator. All it does is add two numbers, like in the last example.

But in this, it will get the numbers from the user!

One simple way to do this is to use the length of the input text as the number: The way we define what we call numbers just so happens (heh) to be such that if we interpret the object for the input string as a number, the number will be the same as the length of the input!

This isn't the greatest solution, but it is easier than other methods. We will use this method first and then move on to other methods that are harder to write, but will be nicer when using the end program.

HERE WE GO:

ok, so like I said, much of it is pretty much the same as that previous program, so we might as well just include said here:

SOME CODE TO GET A AND B HERE import bluh BLAH; BIFURCATE [BLAH,A]ATEMP; BIFURCATE [BLAH,B]BTEMP; BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,NULL]C; BIFURCATE C[JUNK,C]; ~ATH(ATEMP){ BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE [BLAH,C]C; } ~ATH(BTEMP){ BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,C]C; } BIFURCATE [BLAH,C]CTEMP; BIFURCATE CTEMP[JUNK,CTEMP]; ~ATH(CTEMP){ BIFURCATE CTEMP[JUNK,CTEMP]; print some text; } print DONE!; 

so pretty much what we need to do it put the code to get A and B where that goes(at the beginning), as well as stuff to tell the user how to print stuff.

Like I said, the objects from the input commands can be interpreted as numbers.

so this becomes:

print INPUT SOMETHING WITH THE NUMBER OF CHARACTERS AS THE FIRST NUMBER YOU WANT TO ADD; INPUT A; print INPUT SOMETHING WITH THE NUMBER OF CHARACTERS AS THE SECOND NUMBER YOU WANT TO ADD; IMPORT B; import bluh BLAH; BIFURCATE [BLAH,A]ATEMP; BIFURCATE [BLAH,B]BTEMP; BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,NULL]C; BIFURCATE C[JUNK,C]; ~ATH(ATEMP){ BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE [BLAH,C]C; } ~ATH(BTEMP){ BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,C]C; } BIFURCATE [BLAH,C]CTEMP; BIFURCATE CTEMP[JUNK,CTEMP]; ~ATH(CTEMP){ BIFURCATE CTEMP[JUNK,CTEMP]; print some text; } print DONE!; 

So yeah. That should work. I still need to test this, but I am pretty dang sure that this works.(have to go do homework now) In the next post I will explain how to make it so that the user can type in the number as an actual number!


Tags
12 years ago

Conditionals and (finite) loops

In drocta ~ATH, the control flow (what part of the program is run when) is almost entirely determined by ~ATH loops.

The only case where it isn't is when the object initially pointed to by THIS dies. That ends the program immediately. 

This post will show in more detail the basics of its usage.(also introduces the variable NULL)

Is there anything in this post that needs to be clarified?

In a program, you might want something to only happen if something else is true, or you might want it to happen provided that something had not happened.

In many programming languages you would use a command called if.

drocta ~ATH does not have an if statement.

Instead, you create a loop on an object, and inside the loop kill the object.

A little morbid, but isn't ~ATH always?

for example:

SOMECODEHERE ~ATH(SOMEVAR){ SOMEVAR.DIE(); SOMEOTHERSTUFF } SOMEOTHERSTUFF 

However, this isn't the only way. There is another way that is likely preferable in most situations. I just thought this way was the most obvious, and would be an easy way to explain the other method, which is quite similar.

The loop doesn't exactly wait for the object to die, but rather repeats so long as the variable points to an object that is alive. The variable can be made to point to an object that is not alive, either by make the object it points to DIE(), or by making it so it points to a different object that is ALREADY DEAD.

(How can you expect to kill it, when it is ALREADY DEAD?!? haha)

So if the object you wanted the part of the script to run if it was alive was important, and you didn't want to kill it, you could just do this:

BIFURCATE [IMPORTANTOBJECTVAR,IMPORTANTOBJECTVAR]BLAH; BIFURCATE BLAH[V,V]; ~ATH(V){ BIFURCATE [V,NULL]V; BIFURCATE V[JUNK,V]; OTHER CODE TO ONLY EXECUTE IF IMPORTHATOBJECT IS ALIVE } 

Thats nice to be able to do, isn't it.

In fact, it leads nicely into how to make loops that go around a fixed number of times.

suppose if you had

BIFURCATE [BLAH,NULL]V; ~ATH(V){ BIFURCATE V[BLAH,V]; DO OTHER STUFF, POSSIBLY WITH BLAH  }  MORE STUFF 

V would initially be alive, so it would go into the loop, but then V would be made to point to the NULL object, which is dead, so it wouldn't loop the second time.(it would skip to after the loop

that would do the stuff in the loop once.

now what if you wanted to do it twice?

Just make it so it has to bifurcate the thing twice before moving on! Like so:

BIFURCATE [BLAH,NULL]V; BIFURCATE [BLAH,V]V; ~ATH(V){ BIFURCATE V[BLAH,V]; DO OTHER STUFF, POSSIBLY WITH BLAH  }  MORE STUFF 

 this way it will go through the loop, pop off the one side of V, doing the other stuff in the loop. V will still point to something alive after this, so it will do it again, but this time, when it pops off one side of V, the result will be the NULL object, so it will stop.

Thats a loop that goes around twice!

This can be extended to as many number of repetitions as follows:

BIFURCATE [BLAH,NULL]V; BIFURCATE [BLAH,V]V; BIFURCATE [BLAH,V]V; BIFURCATE [BLAH,V]V; ETCETERA BIFURCATE [BLAH,V]V; ~ATH(V){ BIFURCATE V[BLAH,V]; DO OTHER STUFF, POSSIBLY WITH BLAH  }  MORE STUFF 

where the loop will go around however many blahs there are attached to the NULL, because it will keep popping the BLAHs of until it reaches NULL.

The variable V is being used to store how many more loops need to be executed, Which is a number.

V is being used to store a number. 

You might be thinking something along the lines of

"Well this is all very nice, but that seems to only allow for loops that loop a predetermined amount of times."

NOT SO!

You can have another loop that makes a variable point to a number, which would then be in another loop! For example, the following will add two numbers in A and B, store the result in C, copy that result to CTEMP, and then print "some text" the ammount of times in CTEMP!

SOME CODE TO GET A AND B HERE import bluh BLAH; BIFURCATE [BLAH,A]ATEMP; BIFURCATE [BLAH,B]BTEMP; BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,NULL]C; BIFURCATE C[JUNK,C]; ~ATH(ATEMP){ BIFURCATE ATEMP[JUNK,ATEMP]; BIFURCATE [BLAH,C]C; } ~ATH(BTEMP){ BIFURCATE BTEMP[JUNK,BTEMP]; BIFURCATE [BLAH,C]C; } BIFURCATE [BLAH,C]CTEMP; BIFURCATE CTEMP[JUNK,CTEMP]; ~ATH(CTEMP){ BIFURCATE CTEMP[JUNK,CTEMP]; print some text; } print DONE!; 

YAY! We just added two numbers together! In similar ways, we can also subtract, multiply, divide, etcetera! 

if some of this was unclear I would appreciate requests for what needs to be clarified.

Is there anything in this post that needs clarification?


Tags
12 years ago

Syntax explanation post completed, and Hello, World.

I have completed the syntax explanation post, and I think it is fairly clear now.

If you find any part of the post to be unclear, and that it requires further explanation,  please say so so that I can improve it.

Now that that post is in an acceptable form, We can get on to writing our first few ~ATH programs.

print Hello, World.; THIS.DIE(); 

That wasn't so hard, was it?

I feel I should note that the syntax of the print command is not entirely finalized, it might change sometime later.

EXPLANATION:

The first line of the program says to output the text "Hello, World." 

The 2nd line of the program says to end the program. This is because the variable THIS initially points to a object that is only alive when the program is running. If the object is ever not alive, the program stops.

oh gosh why is this a bullet-ed list I am not good with tumblr

To run a drocta ~ATH program, you need the interpreter (available from the github), and python 2.7 (the interpreter can be easily modified to run with python 3, but it is written to work in 2.7)

Open interp_2.py with python, and when the program comes up, type in the filename of the ~ATH program, and hit enter, this will run the ~ATH program.

With this example, it should output the text

Hello, World.

Now, of course, this is a relatively simple program, but at least its something.

Depending on how you are running the interpreter, the program might close immediately after outputting the text.

That might not be what we want.

To make the program not close until we specifically tell it to, we use the following:

print Hello, World.; ~ATH(THIS){ } THIS.DIE(); 

EXPLANATION:

The first line is the same as in the first program. It outputs "Hello, World."

The second line is different, this says to start a loop, which will continue until the object pointed to by the variable THIS is dead.

The third line says to go back to the corresponding ~ATH statement.

The fourth line is never executed, because the loop above it will continue until the object pointed to by THIS dies, and if that object dies the program ends. If it were to be executed it would make the object pointed to by THIS die, and the program would end as a result.

This program should be the same, except that it will keep running until you close it manually.

Now you have hello world written in two different ways!


Tags
12 years ago

Syntax explanation

~ATH is a programming language. A programming language is a language that can be used to write programs in, that can afterwards be run. ~ATH appears in Homestuck, and drocta ~ATH is my attempt at making it a real thing.

drocta ~ATH is limited to what is physically possible of course, because it actually exists. It is also limited to fit well with the comic, and how much of it I have created so far.

As such, so far all the programs that can be written in drocta ~ATH are text only, do not yet accept input (input in progress), and tend to be stupidly long.

It is however capable of computing anything a computer can given enough time and memory.

~ATH is based on objects, and the lives thereof. 

For example, in homestuck, there are programs that relate things to the lifespan of a universe, or a person, etc.

Of course, in order to make an interpreter possible, we have to limit ourselves to virtual objects. Ones that do not actually exist.

References to these objects are stored in things called variables. You probably know what these are already, but if you don't, think of a variable as a box that can have a thing in it. Each box has a name. You can say "do something with whatever is in the box called "apple".

In ~ATH, every object is either "alive" or "dead".  Note that it is the object that is alive or dead, not the variable that refers to the object.

Now onto the actual syntax!:

Currently(as of build 7), drocta ~ATH has 5 different commands: import, ~ATH(){}, .DIE();, print, and BIFURCATE.

First we will go over the import statement. The import statement has the purpose of creating a new variable and a new object. Unlike other operations that can create a new object, the object created by import is initially unrelated to all of the other objects.

The syntax of the import command is:

import anything other than semicolons here VARIABLENAME;

The things between import and the last space before the semicolon are ignored.  

In future versions, the import statement might also do additional things, such as using things from other files. But for now it just initializes variables.

EXAMPLES:

If you wanted to make a new variable called BANANA, and you wanted the reader to know that BANANA is a fruit, you would say:

import FRUIT BANANA;

or you could say

import YELLOW FRUIT BANANA;

The things that go before the variable name don't actually matter, you can say

import ghsdgh hgsdkhg hgksdhg hgskdjg BANANA;

if you wanted.

Now for the next command: The eponymous ~ATH loop!

The syntax of it is as follows:

~ATH(VARNAME){ Some other code goes here }

What this does, is each time the code execution gets to the ~, it checks what the variable in the parentheses is, and then checks the object the variable points to. If the object is alive, it continues. If the object is dead, it skips to after the }. When the Code execution reaches the }, (that is, if it did not skip to after it), it will jump back to the corresponding ~. Code execution will keep going around in this loop until the object pointed to by the variable is not alive. In later versions, there may be an additional requirement that the } be followed by EXECUTE(code here); Where code here can be replaced with ~ATH code, NULL, or possibly a file name. But currently, this is not the case. Now onto the command BIFURCATE!: Bufurcate actually has 2 forms, the standard bifurcate, And the reverse bifurcate. The first of the two has syntax as follows:

BIFURCATE VARNAME1[VARNAME2,VARNAME3];

What this does, is it takes the object pointed to by the first variable, and determines two objects, which are stored in the other two variables. The two objects determined will always be the same for a particular object.  If you for example say:

BIFURCATE V1[V2,V3]; V2.DIE(); BIFURCATE V1[V4,V5]; 

then V4 and V2 will point to the same object, which will be dead.

The other form of the BIFURCATE command has syntax as follows:

BIFURCATE [VAR1,VAR2]VAR3;

This is pretty much the inverse operation. That is, it undoes the other one. If you say for example:

BIFURCATE A[B,C]; BIFURCATE [B,C]D; 

then A and D will point to the same object. To be clear, undoing the other is not the only time you can use it. It will take any two objects, and determine an object from those two. If there is already an object for the combination of those two, then that object is the resultant object. If none has been created yet (and the two arent split from something in that order), it will create a new object, which it will put in VAR3.

To be clear, if you say:

BIFURCATE A[B,C]; BIFURCATE [C,B]D; 

 A and D will NOT point to the same object, unless you create A such that B and C are the same. That is, if you say:

BIFURCATE [Y,Y]A; BIFURCATE A[B,C]; BIFURCATE [C,B]D; 

 A and D WILL point to the same object, and B and C will both point to the same object as Y (and as each other).

The Final command is print.

print is pretty simple, but its syntax might change somewhat.

Currently the syntax is:

print the text you want to output;

Note the semicolon. the semicolon is important.

So hello world would be

print Hello, World.;

SYNTAX EXPLANATION COMPLETE! PLEASE SUGGEST CLARIFICATIONS IF NECESSARY.

MESSAGE END.


Tags
12 years ago

Welcome.

If its not obvious, this blog will teach techniques in a version of ~ATH Specifically, drocta ~ATH. And yes, I'm serious. I believe that I probably am the author of the longest ( possibly up to third longest) ~ATH program. Specifically, bubble sort. Further, I believe I am the author of the first ~ATH interpreter. (I am the drocta of drocta ~ATH) Link here: http://www.mspaforums.com/showthread.php?50314-ATH-interpreter This blog is intended to serve as a tutorial on writing things in drocta ~ATH. First I will go over the syntax. Then how to make conditional like things. Then how to make finite loops. Then perhaps storing "numbers". Then copying "numbers" Then comparing "numbers" Then lists In such a way I intend to work our way up to you understanding how to write bubble sort in drocta ~ATH. After that, we might even implement brainf*** in it. Or a universal Turing machine. Of course, when I say "numbers", the quotes are there for a reason. Numbers are not built into drocta ~ATH. One has to build them. Now how do I tag things...? Ah, that's how. In case it wasn't clear, the interpreter for drocta ~ATH does not attempt the impossible. It cannot trigger the apocalypse. It's just a python script that interprets ~ATH scripts. Don't worry if you don't already know how to program. I intend to make the posts fairly accessible.


Tags
1 month ago
Adult Ath From Radiant Historia (Perfect Chronology)

Adult Ath from Radiant Historia (Perfect Chronology)

I've finished the game recently, and I really liked it ! I've seen lot of flaws in it too, including the sexualisation of female characters. Like. Come on. Ath is 9 ! Can you just give her a shirt ?

So here's a redesign, imagining her older, more dressed, and with a red scarf that remind her of a certain someone...


Tags
Loading...
End of content
No more pages to load
Explore Tumblr Blog
Search Through Tumblr Tags