From a mathematical point of view what you want is a function that is not inversable, ie. non-injective. Consider for example the function $f_1(x)=\lfloor x/10 \rfloor$ (where $\lfloor \cdot \rfloor$ means "round down"). This function will map the values $\{0,1,2,..,8,9\}$ to $0$. So if you only know that the output was $0$, it is impossible to know which input it was. Of course this is not a very good hashing function, as there are only 10 rather obvious possibilites, but it would qualify as being a "one way function" anyways.
In practice it is more important that it is very hard to invert the function rather than it really being non-invertible. If you restrict yourself to inputs of 16 characters or less a hash function like sha, md5 etc. might very well be invertible, but the only way to know would be to calculate every input-ouput pair. In the above example $f_1$ was easy to "invert" because it was such a simple function. To make in cryptografically more robust you would add a lot of complexity....
The most commonly used non-invertable map (as part of a much more complex algorithm) is the modulo operation. It is the rest of an integer devision eg. let $\%$ denote the modulo operator, then $1\%3=1$, $2\%3=2$, $3\%3=0$, $4\%3=1$ ... (this might be "hidden" in the form of an overflow in an addition etc. but is still present in most modern hash algorithms)
Use this modulo operator in a few places, and chances are, you already have an acceptable hash algorithm (assuming it does not have to stand against serious attacks). For example:
$ (a\cdot x^n) \% m $ for proper $a,n,m\in\mathbb{N}$. or:
$ h(n) = (m\cdot h(n-1) + a_n)\%p\quad\quad h(0)=q\quad\quad m,p,q\in\mathbb{N} $
where $a_n$ is the sequence of input bytes and $h(n)$ gives the hash of the first $n$ bytes. For more examples you can easily check the wikipedia.
Of course, the more security you want, the more constraints there are going to be on your algorithm. What should be the time constraint for a single hash? How many different hashes should there be? Of course every possible output should be roughtly equally likely... And should change as much as possible even if you only change one bit of the input..... The list goes on, so that modern hashes really are not that trivial anymore, trying to comply with as many such constraints as possible.