Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 190 191 [192] 193 194 ... 796

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 887575 times)

Skyrunner

  • Bay Watcher
  • ?!?!
    • View Profile
    • Portfolio
Re: if self.isCoder(): post() #Programming Thread
« Reply #2865 on: September 04, 2012, 09:02:16 am »

Nooo...what's a dot product... @_@
A dot product is a math thing, not a programming thing. And if you read alway's post, you've already learned everything a dot product can do for you.
I do know that it's math, because a big part of senior math in  high school here is Geometry and Vectors xD

how it works. I'm working with these 4D-tensors now and I'm all like Copy-Paste-Fuckdatshit and it works and I don't really need to know how it works internally, as long as it does the job.
That made me laugh xD

All those experienced programmers who seem to know every nook and cranny of C++/C++11 are scary though <.< I didn't know while(std::cin>>string) was a thing, either, nor that you can make a 18 line program that counts unique words in a text file for you. Maybe I'm just lacking in experience ._.
Logged

bay12 lower boards IRC:irc.darkmyst.org @ #bay12lb
"Oh, they never lie. They dissemble, evade, prevaricate, confoud, confuse, distract, obscure, subtly misrepresent and willfully misunderstand with what often appears to be a positively gleeful relish ... but they never lie" -- Look To Windward

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2866 on: September 04, 2012, 09:36:26 am »

Yep; the dot product is really easy to compute. You can even have a simple algorithm to find any dot product of any dimension of vector:
Code: [Select]
float dotProduct(floatArray vector1, floatArray vector2, int numDimensions)
{
    float dotproduct = 0;
    for(int i=0; i<numDimensions; i++)
       dotproduct += vector1[i] * vector2[i];
    return dotproduct;
}
So it's just a simple thing where you multiply the Ith element in the first with the Ith element in the second, then add all the resulting numbers together.

As for what it is doing, it's essentially projecting one vector into the direction of the other, then multiplying the resulting scalars. Imagine a graph with 2 lines going from the origin to 2 arbitrary points. Now, rotate that graph around the origin such that one of the points is travelling along the X axis. Then, draw a vertical line to the x axis from the second point. Take the length from the origin to the first point and the length from the origin to the vertical point on the x axis from the second point. Now multiply them together. That's the dot product. By dividing that number by the lengths from the origin to point 1 and point 2, you will get the x component of a unit vector from which you can take the inverse cosine to get the angle between the two.
theta = cosinverse([A dot B] / [length A * length B])
« Last Edit: September 04, 2012, 10:16:12 am by alway »
Logged

ECrownofFire

  • Bay Watcher
  • Resident Dragoness
    • View Profile
    • ECrownofFire
Re: if self.isCoder(): post() #Programming Thread
« Reply #2867 on: September 04, 2012, 09:54:34 am »

If you want a library to do vectors for you (especially ones that involve OpenGL), GLM is a very nice header-only library (all you need to do is drop it in a folder somewhere and #include the parts you need). It basically brings GLSL math functions into C++. You're not forced to use them for OpenGL, but that's their recommended usage.
Logged

MorleyDev

  • Bay Watcher
  • "It is not enough for it to just work."
    • View Profile
    • MorleyDev
Re: if self.isCoder(): post() #Programming Thread
« Reply #2868 on: September 04, 2012, 10:14:57 am »

Vector maths is one of those things that for me just clicked one day. Same with matrices. Now I just need quaternions to click and I'll be golden ;-)
« Last Edit: September 04, 2012, 10:20:43 am by MorleyDev »
Logged

Mego

  • Bay Watcher
  • [PREFSTRING:MADNESS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2869 on: September 04, 2012, 02:04:05 pm »

All those experienced programmers who seem to know every nook and cranny of C++/C++11 are scary though <.< I didn't know while(std::cin>>string) was a thing, either, nor that you can make a 18 line program that counts unique words in a text file for you. Maybe I'm just lacking in experience ._.

Reading reference material and other people's code is the usual way I learn new tricks with C++. The trick that you mentioned with std::cin is due to the fact that operators are essentially functions with special calling syntax, combined with a special operator defined in the std::ios class (which std::istream, the class that std::cin is an object of, inherits from).

Part 1: Basic Operators

Operators are functions with special syntax and conventions on precedence. What does that mean? Well, let's say we wanted to add 2 to the product of 314 and 628. With normal functions, we'd have to do the order of operations ourself:

Code: [Select]
// plus(int, int) and multiplies(int, int) do exactly what you would expect

#include <iostream>
#include <functional> // plus(int, int) and multiplies(int, int) are functions in this header, in a slightly different form involving templates

using namespace std;

int main() {
    cout << plus(2, multiplies(314, 628)); << endl;
    return 0;
}

// Note: I could have written my own functions for adding and multiplying two integers, but the standard library provides them for me, so I decided to use them instead.

Sure, that's manageable now, but what if you had a bunch of operations strung together? Unless you're a LISP programmer, you probably don't want to keep up with all of those parentheses around the argument lists. What if you get one in the wrong place? If you're lucky, you'll get a wrong answer. If you're unlucky, your code won't compile. So, to make things more aesthetically pleasing in the code, we have these nice little things called operators.

Code: [Select]
#include <iostream>

using namespace std;

int main() {
    cout << 2+314*628 << endl;
    return 0;
}

That looks much nicer, and it has the added benefit of being identical to standard mathematical notation. But what if we had some fancy wrapper class for integers? If we wanted to use operators with that, we'd need to define our own. There's two methods of doing this, and of course there are people who will argue endlessly about which way is better. Let's look at one of them:

Code: [Select]
class SomeClass {
    int A;
public:
    SomeClass(int a) {
        A = a;
    }
    SomeClass operator+(SomeClass other) {
        return A + other.A;
    }
};

We have to do this because the compiler isn't going to make assumptions about how user-defined classes should act with standard operators. No matter how annoying that may seem at times, it is certainly for a good reason. When a language guesses what you mean, you get... Well...

Spoiler (click to show/hide)

Anyways! Notice that the operator definition has a return type, just like a normal function. It evaluates just like a function, and returns a SomeClass object.

So that's the first part of how that trick works. But wait! std::operator>>(istream&, string&) returns an istream&, not a bool! Well...

Part 2: Special Operators and Casting

Yes, that's right. Operators can be used for casting. You read that right. In addition to the standard operators (+,-,*,/,%,^,&,|,&&,||,=,==,+=,-=,*=,/=,%=,&=,|=,^=,.,::,?:,&,..., did I miss any?), you can also define operators that control how an object of one class is casted to an object of a second class. The best part? That second class can be *any* class that can be constructed (aka not abstract), even user-defined classes. Let's look at an example:

Code: [Select]
class SomeClass {
    int A;
public:
    SomeClass(int a) {
        A = a;
    }
    SomeClass operator+(SomeClass other) {
        return A + other.A;
    }
    operator int() {
        return A;
    }
};

That looks just like the other operator definitions, only with 3 significant differences. First off, it does not accept any arguments. That's true for all casting operators. Second, the operator name is the name of the class that you are casting the object into. Third, there is no return type before the operator keyword. That's because of #2; the return type is in the definition as the operator name.

std::istream has an operator defined that casts objects to the void* type, returning a null pointer if none of the error flags are set (like the end of stream flag, which is set when the source stream runs out of data to be read), and a non-null pointer otherwise. It doesn't actually point to anything (in theory, it could, but the pointer is not meant to be dereferenced). Why have this? Well, pointers are implicitly castable to bools; a null pointer casts to false, and aany non-null pointer casts to true.

So there you go, an overly-long explanation for a simple trick. That little piece of code continually reads strings (actually C-style strings, not std::string's) in from standard input, stores them in the string variable, and returns its error state, which is evaluated by the while-loop to determine if it's alright to keep going.

MagmaMcFry

  • Bay Watcher
  • [EXISTS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2870 on: September 04, 2012, 02:54:43 pm »

I didn't know while(std::cin>>string) was a thing, either, nor that you can make a 18 line program that counts unique words in a text file for you. Maybe I'm just lacking in experience ._.

Code: (Perl) [Select]
$_{$_}++ for map {split} <>;
print scalar keys %_;
Logged

dreadmullet

  • Bay Watcher
  • Inadequate Comedian
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2871 on: September 04, 2012, 03:50:12 pm »

Code: (Perl) [Select]
$_{$_}++ for map {split} <>;
print scalar keys %_;

???...What. Where's the text file defined at?! Arrrgh, my brain. Could you explain, character by character, what that code does?
Logged

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2872 on: September 04, 2012, 04:35:45 pm »

It's actually really easy to make a 1 line program to do that in C++. Just don't hit enter. :P
Logged

MagmaMcFry

  • Bay Watcher
  • [EXISTS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2873 on: September 04, 2012, 05:10:46 pm »

AHAHA ADVANCED PERL FTW

Okay, let's go through this step-by-step.

Code: [Select]
<>
The <INPUT> operator takes an input filehandle and pulls text from it. For example, <STDIN> pulls from STDIN, the default console input filehandle. If <> is called in scalar context, it returns a string consisting of the next line of the filehandle. If it is called in list context, it returns a list full of strings containing all the remaining lines of the filehandle. Now if you call <> without a filehandle, then it will return text from the concatenation of all the files whose names are currently in the @ARGV array. Now the @ARGV array is special, because it isn't empty by default, but contains all the command-line arguments given to the program on execution. So if you call <> in list context without a filehandle, it returns all of the contents of the files specified in the command line, broken up by line. Effing powerful.

Code: [Select]
map {split} <>
The map operator map TRANSFORMATION ARGUMENTS takes a transformation subroutine and a list of arguments. The transformation is given by either a subroutine reference, or by an anonymous in-place subroutine defined like this: sub {CODE; CODE; MORE CODE}. Because Perl is nice, it lets you omit the "sub" after a "map". Now what does map do? Basically, it transforms all the ARGUMENTS by applying the TRANSFORMATION to every one of them, and returns a list of all return values. It does this by setting a special variable $_ to the first ARGUMENT, then running the TRANSFORMATION, then setting $_ to the second ARGUMENT, etcetera. Now let's look at the TRANSFORMATION. The split(PATTERN, STRING) command takes a pattern and a string. It searches the string for all occurrences of the PATTERN, and cuts them out. The remaining pieces of the STRING are put into a list and returned. If split isn't given a STRING, it defaults to a special variable, you guessed it, $_. If split isn't even given a PATTERN, it defaults to splitting on whitespace. So map {split} <> returns a list of all the words of all the lines of all the files named in @ARGV.

Code: [Select]
++$_{$_} for map {split} <>;
Now you've probably seen the C-style for (a;b;c) {doThisShit}. Perl has that too, but Perl also has a different form: for $var (LIST) {doThisShit}. In this case, doThisShit is executed once for every element in the LIST, and $var is assigned the corresponding list element in every cycle. Now Perl is awesome, so this second form is also possible in postfix notation. As an example, look at the syntax for Perl's if. There are two ways to use if: the standard C-style if (thisIsTrue) {doThis}, but also doThisShit if thisIsTrue, because both forms are correct english grammar and Perl is awesome. Now if you want to use the second form of "for" in postfix notation, you can type doThisShit for LIST.
Note that you can't specify $var anymore, so (you probably knew by now) $_ is used instead. Note that for (LIST) {} also defaults to $_. So the code above does "++$_{$_}" once for every word in every line in every file named in @ARGV. But what is ++$_{$_}? Well, I introduce you to a type of variables called hashes. They're sorta like C++'s map<string, anything>. You access the whole hash by typing %hashName, and a certain element by $hashName{indexString}. Note that %_ is something completely different from $_, and also from @_. Who cares. So "++$_{$_}" says that the element $_ of %_ shall be incremented. If an element of %_ does not exist, accessing that element will return undef, and adding 1 to undef will return 1, so at the end of the for loop, %_{"string"} will contain the exact number of times that the word "string" has appeared in the files of @ARGV.

Code: [Select]
print scalar keys %_This one is easy: "keys %HASH" returns either an unsorted list of the all the defined keys in %HASH (if it is called in list context), or simply their amount (in scalar context). Note that "print" by itself would enforce list context, but if you want scalar context, just place a "scalar" in between. So print scalar keys %_ will print the amount of entries in %_, and since %_ has exactly one entry for all unique words in the @ARGV files, this will print the number of unique words in the files. By the way, if you call keys without an argument, it defaults to %_. So you could also have written the second line as "print scalar keys;" and it would have worked the same way. I just forgot to omit that. :')




Logged

Skyrunner

  • Bay Watcher
  • ?!?!
    • View Profile
    • Portfolio
Re: if self.isCoder(): post() #Programming Thread
« Reply #2874 on: September 04, 2012, 05:18:23 pm »

How do you make it count unique words? That's what the C++ did.
Logged

bay12 lower boards IRC:irc.darkmyst.org @ #bay12lb
"Oh, they never lie. They dissemble, evade, prevaricate, confoud, confuse, distract, obscure, subtly misrepresent and willfully misunderstand with what often appears to be a positively gleeful relish ... but they never lie" -- Look To Windward

MagmaMcFry

  • Bay Watcher
  • [EXISTS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2875 on: September 04, 2012, 05:21:27 pm »

But it does count unique words! At the end of the loop, %_ contains one entry for every unique word, its value being the amount of times it showed up. And the printed output is the amount of entries in %_, therefore the amount of unique words. All there in my explanation. Ya don't believe Perl, do you?

Oh, and BTW:
It's actually really easy to make a 1 line program to do that in C++. Just don't hit enter. :P
Actually, you need a few #include declarations, and they have to be on their own lines.
« Last Edit: September 04, 2012, 05:25:58 pm by MagmaMcFry »
Logged

Skyrunner

  • Bay Watcher
  • ?!?!
    • View Profile
    • Portfolio
Re: if self.isCoder(): post() #Programming Thread
« Reply #2876 on: September 04, 2012, 05:25:13 pm »

Ooh. Clever :D I just realized that you hashed/stored them in a hash, the words xD

Perl... seems a bit too compactable for comfort D:
Logged

bay12 lower boards IRC:irc.darkmyst.org @ #bay12lb
"Oh, they never lie. They dissemble, evade, prevaricate, confoud, confuse, distract, obscure, subtly misrepresent and willfully misunderstand with what often appears to be a positively gleeful relish ... but they never lie" -- Look To Windward

Valid_Dark

  • Bay Watcher
  • If you wont let me Dream, I wont let you sleep.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2877 on: September 04, 2012, 05:33:58 pm »

Spoiler:  me being dumb (click to show/hide)
« Last Edit: September 04, 2012, 06:02:20 pm by Valid_Dark »
Logged
There are 10 types of people in this world. Those that understand binary and those that don't


Quote
My milkshake brings all the criminals to justice.

Mego

  • Bay Watcher
  • [PREFSTRING:MADNESS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2878 on: September 04, 2012, 05:41:39 pm »

I didn't know while(std::cin>>string) was a thing, either,

std::cin>>string
is only a thing if you are using
Code: [Select]
using namespace std::string;otherwise it would be
Code: [Select]
std::cin>>std::string;or you could use
Code: [Select]
using namespace std;and then it would just be
Code: [Select]
cin>>string;
this also applies when using it as an argument for a while loop, like you first did,
I just didn't feel like typing while,.. it's such a ..strange... word

Actually, it is. Since the using directive has clearly not been used, string is a perfectly acceptable identifier for a variable. I assumed that it was being used as such.

Valid_Dark

  • Bay Watcher
  • If you wont let me Dream, I wont let you sleep.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #2879 on: September 04, 2012, 06:01:36 pm »

ahhhh you're right, I don't know what I was thinking,
I just woke up, sorry

well you'd still have to declare the variable with std::string, :P
« Last Edit: September 04, 2012, 06:04:49 pm by Valid_Dark »
Logged
There are 10 types of people in this world. Those that understand binary and those that don't


Quote
My milkshake brings all the criminals to justice.
Pages: 1 ... 190 191 [192] 193 194 ... 796