all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: tpeplt <tpeplt@gmail.com>
To: uzibalqa <uzibalqa@proton.me>
Cc: <help-gnu-emacs@gnu.org>
Subject: Re: Too many permutations computed
Date: Thu, 03 Aug 2023 14:23:02 -0400	[thread overview]
Message-ID: <873510f0jd.fsf@gmail.com> (raw)
In-Reply-To: <Ug13lSJeexzDXPneYyL05De7rscBvpDaUTim67wfYWqxZXVdHe_WPbRaO-2yPZaeG44o2IQC45AABu0SWfWXoaPCUJ8dxXfcbi7T8Yt9Ktg=@proton.me> (uzibalqa@proton.me's message of "Tue, 01 Aug 2023 18:45:08 +0000")

uzibalqa <uzibalqa@proton.me> writes:

> I have implemented the computations of permutations of a string using the heap algorithm.
>

1. Here are the relevant lines of the algorithm* that you cited:

>         // Initially k = length(A)
>         generate(k - 1, A)
>
>         // Generate permutations for k-th swapped with each k-1 initial
>         for i := 0; i < k-1; i += 1 do

Note that in the ‘for’ statement, the condition is i < k-1.  This is due
to indexing starting at zero, i := 0, so indexing is from zero to length
- 1.  In your procedure, you have indexing ranging from zero to length:

>         (while (< j h)...

When this is changed to (while (< j (1- h))..., the procedure works
correctly.

*Heap’s Algorithm is named after B.R. Heap, rather than for ‘heap’ or
‘the heap’.

Here are some additional notes, but it should be possible to ignore them
and simply make the change above to get your procedure to work.

2. Your procedure contains the following expression that does not appear
to do anything so it might as well be deleted.

>   (if (null result) (setq result '()))

Here is the complete listing of your procedure with the changes listed,
above:

(defun permute-strg-heap (strg h result)
  "Collect permutations of string STRG of length H into list RESULT.
Use Heap’s Algorithm for computing all permutations."
  (if (= h 1)
      (progn
        (push (copy-sequence strg) result) ; Output the permutation
        (message "%s" strg))
    
    (progn
      (setq result
            (permute-strg-heap strg (1- h) result))
      (let ((j 0))
        (while (< j (1- h))
          ;; Generate permutations for i-th swapped with each i-1 initial
          ;; Swap choice based upon h (even or odd)
          (if (evenp h)
              (swap-chars strg j (1- h))
            (swap-chars strg 0 (1- h)))
          (setq result
                (permute-strg-heap strg (1- h) result))
          (setq j (1+ j))))))
  result)

3. No definition of the procedure ‘swap-chars’ was included in your
post.  Here is a simple (destructive) one that works with your
procedure:

(defun swap-chars (str p q)
  "Swap characters at indices P and Q in string STR.
This is destructive, that is, the value of STR is changed/lost."
  (let ((tmp (elt str p)))
    (aset str p (elt str q))
    (aset str q tmp)))

(setq my-string "abc")
my-string
=> "abc"

(swap-chars my-string 0 2)
my-string
=> "cba"

4. A wrapper procedure could be added for safety and convenience.

(defun permute (strg)
  "Generate a list of all permutations of the characters in string STRG."
  (if (string-empty-p strg)
      (list strg)
    (permute-strg-heap strg (length strg) '())))

(permute "")
=> ("")
(permute "a")
=> ("a")
(permute "ab")
=> ("ba" "ab")
(permute "abc")
=> ("cba" "bca" "acb" "cab" "bac" "abc")

This procedure will protect against empty strings that could lead to a
run-time error.  And it eliminates the need for the user to compute (or
make a mistake) the string’s length or to enter the constant '().

--



  parent reply	other threads:[~2023-08-03 18:23 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-01 18:45 Too many permutations computed uzibalqa
2023-08-02 10:13 ` Emanuel Berg
2023-08-03 15:42   ` uzibalqa
2023-08-03 16:49     ` uzibalqa
2023-08-03 22:13       ` Emanuel Berg
2023-08-04 18:44         ` Heime
2023-08-03 15:52   ` uzibalqa
2023-08-03 16:08     ` Emanuel Berg
2023-08-04 18:39       ` Heime
2023-08-03 18:23 ` tpeplt [this message]
2023-08-03 23:25   ` Emanuel Berg
2023-08-04 21:45     ` tpeplt
2023-08-06 13:32       ` Emanuel Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=873510f0jd.fsf@gmail.com \
    --to=tpeplt@gmail.com \
    --cc=help-gnu-emacs@gnu.org \
    --cc=uzibalqa@proton.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.