Programming thread

I think powersets are a good exercise for learning recursion. For the fun of it, I wrote an implementation in Scheme as simply and compactly as I could:
Code:
(define (powerset s)
  (foldr (λ (x r)
           (foldr (λ (y z) (cons (cons x y) (cons y z))) '() r))
         '(()) s))

Output:
Code:
(powerset '(1 4 2 7))
'((1 4 2 7)
  (4 2 7)
  (1 2 7)
  (2 7)
  (1 4 7)
  (4 7)
  (1 7)
  (7)
  (1 4 2)
  (4 2)
  (1 2)
  (2)
  (1 4)
  (4)
  (1)
  ())

You should only need 2 simple recursive functions at most.
A lot of the stuff people say here is too advanced for my current level, so I'll have to revisit it eventually.

Seems like powersets are related to Pascal's triangle, so I tried instead to make a recursive for that one.
Python:
def tri(step, x = [1], y = []):
  print(x)
  if len(x) == step:
    return None

  x.insert(0, 0)
  x.append(0)
  y = [x[i] + x[i + 1] for i in range(len(x) - 1)]

  tri(step, x = y, y = [])

tri(15)
Still tacky.
 
You can start with Fibonacci which I think is classic intro to recursion in programming.
And then there is Depth First Search and Backtracking lists. But prefer easy.
I remember reading some of Classic Computer Science Problems in Python (discounted on Annas Archive of course). Maybe the biggest insight I remember was that DFS and BFS are nearly the same algorithm, with the only change being that DFS uses a stack and BFS uses a queue. Really sheds light on finding the right data structure for whatever task it is you have and reminds me of the time I tried writing a balanced parentheses/brackets/braces checker with no stack. It was a broken byzantine piece of garbage and bringing a stack into the picture like I should have from the outset made getting it right a breeze.
 
A lot of the stuff people say here is too advanced for my current level, so I'll have to revisit it eventually.

Seems like powersets are related to Pascal's triangle, so I tried instead to make a recursive for that one.
(CODE)
Still tacky.
Did you try several triangles in a row? Like so:
Python:
def tri(step, x = [1], y = []):
  print(x)
  if len(x) == step:
    return None

  x.insert(0, 0)
  x.append(0)
  y = [x[i] + x[i + 1] for i in range(len(x) - 1)]

  tri(step, x = y, y = [])

tri(15)
tri(5)
tri(6)
# trollface.jpg
 
  • Agree
Reactions: Hall of Cost Payer
A lot of the stuff people say here is too advanced for my current level, so I'll have to revisit it eventually.

Seems like powersets are related to Pascal's triangle, so I tried instead to make a recursive for that one.
Python:
def tri(step, x = [1], y = []):
  print(x)
  if len(x) == step:
    return None

  x.insert(0, 0)
  x.append(0)
  y = [x[i] + x[i + 1] for i in range(len(x) - 1)]

  tri(step, x = y, y = [])

tri(15)
Still tacky.
It may not be immediately obvious but:
Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.
I don't have a solid intuition on how I'd write this function recursively right now. I'd be inclined to use iteration if I just had to bang something out. But I thought it was worth pointing out that, because of Python's behavior with mutable default arguments, they are typically avoided. Maybe an inner helper function with no default might be useful here.
 
I don't have a solid intuition on how I'd write this function recursively right now. I'd be inclined to use iteration if I just had to bang something out. But I thought it was worth pointing out that, because of Python's behavior with mutable default arguments, they are typically avoided. Maybe an inner helper function with no default might be useful here.
This. The standard pattern is to set the default to None and replace it with the desired default immediately, like so:
Python:
def tri(step, x=None):
    if x is None:
        x = [1]
    print(x)
    if len(x) == step:
        return
    x.insert(0, 0)
    x.append(0)
    y = [x[i] + x[i + 1] for i in range(len(x) - 1)]
    tri(step, x=y)
    # obviously you can just do tri(step, [x[i] + x[i + 1] for i in range(len(x) - 1)]) here
    # but an extra line allows a convenient breakpoint where a learner can look at the result


if __name__ == "__main__":
    tri(15)
The main issue with the original design, after the bugs, is it's not mathematically proper recursion. @We Are The Witches you don't need to pass the array at all, not one, and certainly not two. You need to be calling tri(n-1). This is the "step". Without the step, you don't have a mathematically sound recursion, you just have a function niggerliciously calling itself.
Python:
def tri(n):
    if n == 1:
        print([1])
        return [1]
    x = tri(n - 1)
    x.insert(0, 0)
    x.append(0)
    x = [x[i] + x[i+1] for i in range(len(x) - 1)]
    print(x)
    return x


if __name__ == "__main__":
    tri(15)
If you subtract 1 from n every run and stop at 1, you're mathematically guaranteed to stop (if you don't pass a non-natural number, obviously -- if I were making a library for retards, I'd make it a "helper" function, and the public wrapper that calls it would check the number for naturalness once).

In your original code, you're instead growing the list to the desired length. You wrote the part where you grow it one item at a time correctly, but it's harder to check by sight. More importantly these "business logic" parts differ from function to function. In Pascal Triangle it's one thing, in permutations another, in merge sort still something else. The place where the function calls itself should be 100% unambiguous.
If I fucked up the business logic in my function, it'd still exit on time. If you fucked it up in yours, your processor could theoretically melt.
 
Last edited:
So basically it tries all possible combinations of words from a pool of characters, but without repeating them, so for "XYZ" it should give:
XYZ, XZY, YXZ, YZX, ZXY, ZYX
First, line 2 is completely unnecessary. You take the string and turn it into a list, but the list then stays unchanged. You also save the number of characters in that string/list in a separate variable.
Second, redefining variables like that (string to list) is somewhat niggerlicious. You're not gaining anything, you're not saving memory: when you calling the function from outside and pass the string into it, the string still exists in memory in the outer scope. If you really needed a list to fuck around with it, you should've named it something else.
(But you don't need a list, you only access the list `chars` once, in line 35, and that line works for the string exactly the same way.)

From a purely code quality standpoint, the pre-calculation part (huh?) can be rewritten as
Python:
    cycles = [1]
    combinations = 1
    for i in range(1, len(chars) + 1):
        combinations *= i
        cycles.append(combinations)
    numeric_string = list(range(len(chars)))
    print(f"-- The number of combinations is {combinations} --\n")
or even
Python:
    cycles = [1]
    for i in range(1, len(chars) + 1):
        cycles.append(cycles[-1] * i)
    numeric_string = list(range(len(chars)))
    print(f"-- The number of combinations is {cycles[-1]} --\n")
numeric_string isn't something you need to build dynamically, it's a list of integers from 0 to n-1 inclusive where n is length of input. Once you have your input, it's a constant completely independent from anything else that might be happening.

(It's possible to write it even nicer by using itertools and such, but if we're looking at itertools at all, might as well use the permutations from there; I think extending the scope of this particular learning problem to learning itertools BUT NOT PERMUTATIONS NUH UH is retardedly contrived.)

A bigger issue is this pre-calculation is somewhat cheaty and contrived. Once you've tasked yourself with a recursion learning problem, to restrict your options for the purpose of learning, you should use recursion to solve it! Instead, you're relying on a preexisting mathematical result that you haven't yet earned within the scope of the problem. The factorial formula came from outside the program.

Making the matrix is
Python:
matrix = [[] for _ in range(len(chars))]
# assert matrix[0] is not matrix[1]
Surprisingly for python, this is not a footgun, the lists in the matrix are all different, not shallow views of a single list.

A questionable issue is you're not permuting a list consisting of the actual elements of the input but numeric_string, an artificial proxy for it, then convert it back for output. This is a weird choice. I'm not anywhere good enough at python to say what the drawbacks of permuting raw elements might be, but in most cases you can safely operate on the actual objects, knowing that no extra copies will be created. E.g. if you permute a list in which every item is an episode of Galaxy Express 999 (minus the recap and the three tv specials) in blu-ray, each of the 113 episodes will only be stored in memory the one time, not
22311927486598136465966070212187151182564399087952213171022161345724023063584214692821047352118139068425569179220877461124773845924561575264739138192463311667200000000000000000000000000
times.
Anyway, I'll leave that part as it is for now, but this is how to convert the numeric output back into strings:
Python:
    for batch in matrix:
        print("".join(chars[idx] for idx in batch))

Backing up a step, sorting the matrix is not good. Here's why:
Python:
# this is a test
m = [tuple(reversed(x)) for x in matrix]
msort = sorted(m)
assert m == msort
Sorting imposes order on unsorted data. You have some data, you don't know what the fuck's in it, you need to sort it. Sorting is somewhat hard work, O(n log n) -- read up on algorithm speed later -- that the computer must perform.
But your worker function already produced a matrix in good order, as proven by my code.
In lieu of sorting, you can
Python:
    for batch in matrix:
        print("".join(chars[idx] for idx in reversed(batch)))

Going back to the internals of the worker function,
Python:
    def rec(leftover_pool, times):
        if times == 1:
            matrix[0].append(leftover_pool[0])
            return
        for x in range(times):
            hold = leftover_pool.pop(x)
            matrix[times - 1].extend([hold] * cycles[times - 1])
            rec(leftover_pool, times - 1)
            leftover_pool.insert(x, hold)
this looks better. I replaced the internal loop that adds the element the specified number of times with an extend, took out the base (the times=1 branch) outside the loop where it would be prominent, and replaced the else with the return in the base branch so the business logic would be less tabbed.

And then apply @Shalalallah Akbar 's point about times being superfluous:
Python:
    def rec(pool):
        if len(pool) == 1:
            matrix[0].append(pool[0])
            return
        for x in range(len(pool)):
            hold = pool.pop(x)
            matrix[len(pool)].extend([hold] * cycles[len(pool)])
            rec(pool)
            pool.insert(x, hold)

    rec(numeric_string)

Now the biggest problem is, while this is indeed recursion, you're not actually solving the real problem as stated, you're doing a weird trick to reproduce an external solution. You already know how many times you need to add a number to the matrix (the cycles array: 120 permutations to a list of 5, and 24 permutations to a list of 4), you did not get that part naturally from the recursion.
- instead of using this approach where you work out which character is at a particular position in every single permutation, you should use recursion to build up the permutations themselves, based on the principle that, permutation(string) = character + each permutation in permutation(rest of string), for each character in the string, with the base case of permutation(single letter) = single letter.

So let's rewrite the whole thing.
Python:
# the meta-alphabetic order is left as an exercise for the reader

def all_strings(chars):
    if len(chars) == 1:
        return [chars]
    return [
        "".join((s[:idx], chars[-1], s[idx:]))
        for s in all_strings(chars[:-1])
        for idx in range(len(s)+1)
    ]


if __name__ == "__main__":
    pool = "ABCDE"
    print(all_strings(pool))
4 lines lmao
 
Last edited:
  • Informative
Reactions: Belisarius Cawl
What's a based, free and public alternative to github? I want to get away from microshit's copilot worldwide gangster police communist computer god wall-to-wall surveillance network but I want to be able to share my projects with normies without them being afraid of catching Internet AIDS.
 
r anyone who has experience making console apps in c#. Is Spectre.Console worth using? The documentation seems vague and aside from a few things it just seems to be unnecessary bloat.

Is there any reason why I shouldn't just use the normal vanilla System.Console?

What's a based, free and public alternative to github? I want to get away from microshit's copilot worldwide gangster police communist computer god wall-to-wall surveillance network but I want to be able to share my projects with normies without them being afraid of catching Internet AIDS.
Set up a website, display your code in plain texts so people can see what it does, and then pack it all into a zip folder for anyone who wants to download it.
 
Last edited by a moderator:
  • Agree
Reactions: UERISIMILITUDO
What's a based, free and public alternative to github? I want to get away from microshit's copilot worldwide gangster police communist computer god wall-to-wall surveillance network but I want to be able to share my projects with normies without them being afraid of catching Internet AIDS.
Gitlab( dot com)? Probably not based but should be able to share code at least.
 
Set up a website, display your code in plain texts so people can see what it does, and then pack it all into a zip folder for anyone who wants to download it.
I need it to function as a git remote for myself and also so people can clone my shit with relative user friendliness. I'm not as autistic as Drew DeVault to roll my own public VCS host.
Gitlab( dot com)? Probably not based but should be able to share code at least.
I thought Gitlab was self-host only, do they have a public instance for everyone?
I'm just looking for something like bitbucket that is not github and respects privacy and ideally free speech.
 
  • Like
Reactions: Belisarius Cawl
I need it to function as a git remote for myself and also so people can clone my shit with relative user friendliness. I'm not as autistic as Drew DeVault to roll my own public VCS host.

I thought Gitlab was self-host only, do they have a public instance for everyone?
I'm just looking for something like bitbucket that is not github and respects privacy and ideally free speech.
You're likely to never find a place to say "nigger", or "troons are bad" that you don't host yourself. But gitlab does hosting now:

 
I need it to function as a git remote for myself and also so people can clone my shit with relative user friendliness. I'm not as autistic as Drew DeVault to roll my own public VCS host.
Github can't ban you for tos violations unless you get caught. Use a private repository, maybe.
 
You're likely to never find a place to say "nigger", or "troons are bad" that you don't host yourself. But gitlab does hosting now:

Hard times for BSD+NIGGER license chads.
I've heard good things about Gitlab overall and I like the UI so I'll probably use it, thanks.

Github can't ban you for tos violations unless you get caught. Use a private repository, maybe.
I'm not really worried about freeze peach nearly as much as about privacy. I don't want my shit to become part of some pajeet AI and to give my personal details and 2FA access and shit to the second worst tech corporation.
 
  • Agree
Reactions: Marvin
I'm not really worried about freeze peach nearly as much as about privacy. I don't want my shit to become part of some pajeet AI and to give my personal details and 2FA access and shit to the second worst tech corporation.
IIRC there is a way to opt out of that, but I dont really blame you for whether or not you trust that.

Im still but a learner so all my github shit is just projects I did and some private repos from a few freelance jobs.
 
You're likely to never find a place to say "nigger", or "troons are bad" that you don't host yourself. But gitlab does hosting now:

There's gitgud.io, which hosts +NIGGER licensed software. Most notably Crunklord's Temple OS games.
And there used to be a git host called "gitler.moe", in the theme of anime and Hitler. I think they wouldn't have a problem with bad words.
 
I don't want my shit to become part of some pajeet AI
Then you don't want either Github or Gitlab. Just look at Gitlab's website, they practically scream in your face how they're feeding the electronic pajeet with your code. They claim not to do with with private repos, but depending on how widely you want to share your code, this may or may not be practical.
 
I need it to function as a git remote for myself and also so people can clone my shit with relative user friendliness. I'm not as autistic as Drew DeVault to roll my own public VCS host.
What about hosting Forgejo on some Docker VPS? I wouldn't trust any git provider for not scraping data for AI.
It's just too much money for probably zero consequences.
 
I need it to function as a git remote for myself and also so people can clone my shit with relative user friendliness. I'm not as autistic as Drew DeVault to roll my own public VCS host.

I thought Gitlab was self-host only, do they have a public instance for everyone?
I'm just looking for something like bitbucket that is not github and respects privacy and ideally free speech.
Gitlab has a free public thing that is decent, but they're more CoC-friendly.

Gitgud.io is really nice and fairly liberal ToS-wise. They fund it through other services they offer, so they're less influenced by funding from tranny orgs.
 
I am planning to start developing an android app for myself. Does anyone have any experience in that field with tips or things to keep in mind?
 
Back