POV-Ray : Newsgroups : povray.off-topic : An explanation of what next_permutation does Server Time
4 Sep 2024 19:18:03 EDT (-0400)
  An explanation of what next_permutation does (Message 1 to 10 of 32)  
Goto Latest 10 Messages Next 10 Messages >>>
From: Darren New
Subject: An explanation of what next_permutation does
Date: 3 Dec 2009 02:21:54
Message: <4b176712$1@news.povray.org>
next_permutation being a subroutine in the C++ standard library that gives 
you the lexographically next permutation of an array.

http://wordaligned.org/articles/next-permutation?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+wordaligned+(Word+Aligned)

Interesting. :-)

-- 
Darren New, San Diego CA, USA (PST)
   Human nature dictates that toothpaste tubes spend
   much longer being almost empty than almost full.


Post a reply to this message

From: Invisible
Subject: Re: An explanation of what next_permutation does
Date: 3 Dec 2009 09:08:38
Message: <4b17c666$1@news.povray.org>
Darren New wrote:

> Interesting. :-)

"while (!(*i < *--j)) {}"

Um, yeah, "interesting" would be the term I'd use. WTF? o_O



Personally, I'd do it this way:

nextP :: Ord x => [x] -> Maybe [x]
nextP []  = Nothing
nextP [x] = Nothing
nextP xs  =
   case split (reverse xs) of
     ([] , _  ) -> Nothing
     (ss', ps') ->
       let
         p0         = head ps'
         (ss0, ss1) = span (p0 >=) ss'
         s0         = head ss1
         ps         = reverse (s0 : tail ps')
         ss         = ss0 ++ [p0] ++ tail ss1
       in Just (ps ++ ss)

split :: Ord x => [x] -> ([x], [x])
split [] = ([], [])
split (x:xs) = work x xs
   where
     work x0 [] = ([x0], [])
     work x0 (x:xs)
       | x >= x0   = let (ys,zs) = work x xs in (x0:ys, zs)
       | otherwise = ([x0], x:xs)


Post a reply to this message

From: Darren New
Subject: Re: An explanation of what next_permutation does
Date: 3 Dec 2009 12:34:20
Message: <4b17f69c$1@news.povray.org>
Invisible wrote:
> "while (!(*i < *--j)) {}"

C has always advocated piling up a bunch of side effects inside 
conditionals.   Even to the point where Google's go has completely useless 
syntax for doing so.

In go, you can write
   if x := y + 1; x > 5 { ... }

Which is always exactly precisely the same as
   x := y + 1;
   if x > 5 { ... }

Since you *always* need braces, and the result of evaluating the assignment 
isn't ever used as the conditional, it's just a way of embedding 
side-effects into a part of a statement that should be side-effect free, 
apparently because the people designing go are so used to C's actually 
*useful* side effects that they missed the result.

The above line could also be
   do { j -= 1; } while (*j <= *i);
(or maybe while *i < *j. I don't care to work it out for sure)

So, yeah, it's opaque C++ code there.


> Um, yeah, "interesting" would be the term I'd use. WTF? o_O

The algorithm is interesting, not the implementation.

-- 
Darren New, San Diego CA, USA (PST)
   Human nature dictates that toothpaste tubes spend
   much longer being almost empty than almost full.


Post a reply to this message

From: Warp
Subject: Re: An explanation of what next_permutation does
Date: 3 Dec 2009 14:04:44
Message: <4b180bcc@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Invisible wrote:
> > "while (!(*i < *--j)) {}"

> C has always advocated piling up a bunch of side effects inside 
> conditionals.

  OTOH, once you learn to read it, it's not that bad.

  It's a bit like using "++i" instead of "i = i + 1". The latter might be
clearer at first, but once you understand what "++i" means, not really.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: An explanation of what next_permutation does
Date: 3 Dec 2009 15:00:13
Message: <4b1818cd$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> Invisible wrote:
>>> "while (!(*i < *--j)) {}"
> 
>> C has always advocated piling up a bunch of side effects inside 
>> conditionals.
> 
>   OTOH, once you learn to read it, it's not that bad.

Not in moderation. If something in the condition can't easily be expressed 
outside the condition, it's helpful. For example,
   while (EOF != (c = getchar())) { ... }
You can't really put the assignment outside the condition without 
duplicating that code, and it's kind of an accident of the design of the 
libraries that means you can't find out the result from getchar without 
invoking undesirable side-effect.[1] But convolving the comparison and the 
decrement in this case was unnecessary, I think. Doing the decrement in the 
body would say "keep decrementing until the condition is satisfied", which 
doesn't really come across in the way it's written.

>   It's a bit like using "++i" instead of "i = i + 1". The latter might be
> clearer at first, but once you understand what "++i" means, not really.

You definitely have to look at that expression to figure out what it's 
doing. Of course, they could have reversed the letters and made it a little 
clearer, too.


[1] You don't have this problem with iterators, for example, as you can just 
as for "*j" as often as you want without changing "j".  Eiffel and Ada solve 
it by requiring/suggesting that anything that has side effects doesn't 
return a value. So in Eiffel, there's a (void) procedure to read the next 
character into a buffer inside the object, and a function to get whatever 
character was most recently read, so you don't need to do the assignment 
inside the condition to save the character it returned, the way you need to 
in non-OO C.

-- 
Darren New, San Diego CA, USA (PST)
   Human nature dictates that toothpaste tubes spend
   much longer being almost empty than almost full.


Post a reply to this message

From: scott
Subject: Re: An explanation of what next_permutation does
Date: 4 Dec 2009 10:53:15
Message: <4b19306b@news.povray.org>
>     ([] , _  ) -> Nothing

Yeh, it's really clear what this line does to a non-Haskeller :-)


Post a reply to this message

From: Invisible
Subject: Re: An explanation of what next_permutation does
Date: 4 Dec 2009 10:57:47
Message: <4b19317b$1@news.povray.org>
scott wrote:
>>     ([] , _  ) -> Nothing
> 
> Yeh, it's really clear what this line does to a non-Haskeller :-)

I'll tell you what it does: It makes the function crash. o_O

It *should* in fact be

    (_  , [] ) -> Nothing

It seems I got my arguments the wrong way around. :-/

As for what it *means*, it means that if the prefix is empty ("[]"), 
there is no next permutation ("Nothing"). The "_" simply means that it 
doesn't matter what the suffix part is.


Post a reply to this message

From: Warp
Subject: Re: An explanation of what next_permutation does
Date: 4 Dec 2009 11:19:16
Message: <4b193684@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> scott wrote:
> >>     ([] , _  ) -> Nothing
> > 
> > Yeh, it's really clear what this line does to a non-Haskeller :-)

> I'll tell you what it does: It makes the function crash. o_O

  After this you should really stop picking on C variants (or at the very
least, not immediately compare them to Haskell). ;)

-- 
                                                          - Warp


Post a reply to this message

From: Invisible
Subject: Re: An explanation of what next_permutation does
Date: 4 Dec 2009 11:28:02
Message: <4b193892$1@news.povray.org>
>>>>     ([] , _  ) -> Nothing
>>> Yeh, it's really clear what this line does to a non-Haskeller :-)
> 
>> I'll tell you what it does: It makes the function crash. o_O
> 
>   After this you should really stop picking on C variants (or at the very
> least, not immediately compare them to Haskell). ;)

Why? Because I wrote some code with a small typo?


Post a reply to this message

From: Darren New
Subject: Re: An explanation of what next_permutation does
Date: 4 Dec 2009 11:51:32
Message: <4b193e14$1@news.povray.org>
scott wrote:
>>     ([] , _  ) -> Nothing
> 
> Yeh, it's really clear what this line does to a non-Haskeller :-)

It's pretty standard notation for functional languages. Erlang uses the same 
notation. If you get a two-element tuple with the first element being an 
empty list, the result is an arbitrary atomic value (not unlike an "enum") 
called "Nothing".

It's no less clear than function calls or array indexes if you've ever used 
that operation before in a programming language. It's about as complex as a 
case statement.

-- 
Darren New, San Diego CA, USA (PST)
   Human nature dictates that toothpaste tubes spend
   much longer being almost empty than almost full.


Post a reply to this message

Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.