Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #45615 > unrolled thread
| Started by | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| First post | 2016-02-19 09:00 +0000 |
| Last post | 2016-02-22 09:37 +0000 |
| Articles | 13 — 5 participants |
Back to article view | Back to comp.lang.forth
Reverse a string (with xchars) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-02-19 09:00 +0000
Re: Reverse a string (with xchars) mentificium@gmail.com - 2016-02-20 23:44 -0800
Re: Reverse a string (with xchars) Chris Curl <ccurl609@gmail.com> - 2016-02-21 10:18 -0800
Re: Reverse a string (with xchars) Chris Curl <ccurl609@gmail.com> - 2016-02-21 10:24 -0800
Re: Reverse a string (with xchars) Chris Curl <ccurl609@gmail.com> - 2016-02-21 10:35 -0800
Re: Reverse a string (with xchars) Paul Rubin <no.email@nospam.invalid> - 2016-02-21 12:07 -0800
Re: Reverse a string (with xchars) Chris Curl <ccurl609@gmail.com> - 2016-02-21 12:40 -0800
Re: Reverse a string (with xchars) Paul Rubin <no.email@nospam.invalid> - 2016-02-21 12:50 -0800
Re: Reverse a string (with xchars) Paul Rubin <no.email@nospam.invalid> - 2016-02-21 12:56 -0800
Re: Reverse a string (with xchars) Chris Curl <ccurl609@gmail.com> - 2016-02-21 14:43 -0800
Re: Reverse a string (with xchars) Paul Rubin <no.email@nospam.invalid> - 2016-02-21 14:59 -0800
Re: Reverse a string (with xchars) Chris Curl <ccurl609@gmail.com> - 2016-02-21 16:55 -0800
Re: Reverse a string (with xchars) Albert van der Horst <albert@spenarnc.xs4all.nl> - 2016-02-22 09:37 +0000
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2016-02-19 09:00 +0000 |
| Subject | Reverse a string (with xchars) |
| Message-ID | <2016Feb19.100032@mips.complang.tuwien.ac.at> |
The Rosettacode task posted recently was actually
<http://www.rosettacode.org/wiki/Reverse_words_in_a_string>, but there
is also <http://www.rosettacode.org/wiki/Reverse_a_string>, which
reverses the string character-by-character. There are Forth-94
solutions given there, but with 8-bit or 16-bit characters, these
cannot handle Unicode.
The task is interesting because it is one of the few cases where we
actually need to do something special when dealing with UTF-8, i.e.,
where we actually need words from the xchars wordset for dealing with
UTF-8 (in most other cases, the Forth-94 words are sufficient).
Here's my solution:
\ Has an environmental dependency on 1 chars=1.
\ The xchars wordset offers several ways to skin this cat; I use one,
\ but a different one may be better.
: xreverse {: c-addr u -- c-addr2 u :}
u allocate throw u + c-addr swap over u + >r begin ( from to r:end)
over r@ u< while
over r@ over - x-size dup >r - 2dup r@ cmove
swap r> + swap repeat
r> drop nip u ;
\ Test case
s" ώщыē" xreverse type
The task description says: "For extra credit, preserve Unicode
combining characters." Combining characters consist of several code
points; e.g., "ü" is a precomposed character and has one code point,
but could also be encoded in a decomposed way as a "u" followed by the
combining diacritic character U+308 "diaresis". Because the current
version reverses the code points, it does not work correctly for
decomposed characters.
What is missing from xchars for the extra credit is a way to recognize
combining characters.
While I am at it: a word for validating and normalizing UTF-8 input
would also be a good idea (or split these tasks into several words?).
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/
[toc] | [next] | [standalone]
| From | mentificium@gmail.com |
|---|---|
| Date | 2016-02-20 23:44 -0800 |
| Message-ID | <01ee8042-3397-47bd-beaf-abf479e72d52@googlegroups.com> |
| In reply to | #45615 |
On Friday, February 19, 2016 at 1:29:40 AM UTC-8, Anton Ertl wrote:
> The Rosettacode task posted recently was actually
> <http://www.rosettacode.org/wiki/Reverse_words_in_a_string>, but there
> is also <http://www.rosettacode.org/wiki/Reverse_a_string>, which
> reverses the string character-by-character. There are Forth-94
> solutions given there, but with 8-bit or 16-bit characters, these
> cannot handle Unicode.
>
> The task is interesting because it is one of the few cases where we
> actually need to do something special when dealing with UTF-8, i.e.,
> where we actually need words from the xchars wordset for dealing with
> UTF-8 (in most other cases, the Forth-94 words are sufficient).
>
> Here's my solution:
>
> \ Has an environmental dependency on 1 chars=1.
>
> \ The xchars wordset offers several ways to skin this cat; I use one,
> \ but a different one may be better.
>
> : xreverse {: c-addr u -- c-addr2 u :}
> u allocate throw u + c-addr swap over u + >r begin ( from to r:end)
> over r@ u< while
> over r@ over - x-size dup >r - 2dup r@ cmove
> swap r> + swap repeat
> r> drop nip u ;
>
> \ Test case
> s" ώщыē" xreverse type
>
> The task description says: "For extra credit, preserve Unicode
> combining characters." Combining characters consist of several code
> points; e.g., "ü" is a precomposed character and has one code point,
> but could also be encoded in a decomposed way as a "u" followed by the
> combining diacritic character U+308 "diaresis". Because the current
> version reverses the code points, it does not work correctly for
> decomposed characters.
>
> What is missing from xchars for the extra credit is a way to recognize
> combining characters.
>
> While I am at it: a word for validating and normalizing UTF-8 input
> would also be a good idea (or split these tasks into several words?).
>
> - anton
> --
> M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
> comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
> New standard: http://www.forth200x.org/forth200x.html
> EuroForth 2015: http://www.rigwit.co.uk/EuroForth2015/
I did not know that Forth could handle UTF-8 and Unicode.
I am trying to translate
http://www.nlg-wiki.org/systems/Mind.Forth into
http://ai.neocities.org/perlmind.txt (Perl artificial intelligence)
as an AI that shall use Unicode to think in
English, German and Russian but the Unicode
is very difficult for me to get a grip on.
I am setting up a MindBoot sequence with
English at timepoints 0 to 651 (up to 999);
Russian at timepoints 1001 to 1577 (up to 1999); and
German at timepoints 2001 to 3215 (and beyond).
I appreciate the above post about Forth Unicode.
- arthur
--
http://ai.neocities.org/P6AI_FAQ.html
http://ai.neocities.org/P6AI_man.html
http://ai.neocities.org/AiSteps.html
http://ai.neocities.org/PMPJ.html
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-02-21 10:18 -0800 |
| Message-ID | <f9be8844-ca23-49c8-96e1-efb307d6e831@googlegroups.com> |
| In reply to | #45615 |
On Friday, February 19, 2016 at 4:29:40 AM UTC-5, Anton Ertl wrote: \ reverse a string in place : str.reverse ( addr -- ) count over + 1- ( start end ) begin 2dup > ( start end bool ) if 2drop exit then ( start end ) over c@ over c@ ( start end start-ch end-ch ) 3 pick c! ( start end start-ch ) over c! ( start end ) 1- swap 1+ swap ( new-start new-end ) again ;
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-02-21 10:24 -0800 |
| Message-ID | <c984e8ae-513a-441b-9897-8cfd40f36499@googlegroups.com> |
| In reply to | #45654 |
I know that doesn't address the question ... all it does is reverse a counted string in place. i'll start the wheels in the back of my head turning on the other thing.
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-02-21 10:35 -0800 |
| Message-ID | <d1e1967f-6c07-4d04-867f-45133642a540@googlegroups.com> |
| In reply to | #45655 |
I guess I'm having a hard time understanding what the difficulty is. Since each unicode UTF-16 character is 2 bytes instead of 1, why wouldn't something like this work? \ reverse a UTF-16 string in place : str.reverse.UTF-16 ( addr -- ) count over + 2 - ( start end ) begin 2dup > ( start end bool ) if 2drop exit then ( start end ) over 16@ over 16@ ( start end start-ch end-ch ) 3 pick 16! ( start end start-ch ) over 16! ( start end ) 2- swap 2+ swap ( new-start new-end ) again ;
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2016-02-21 12:07 -0800 |
| Message-ID | <874md16d46.fsf@jester.gateway.pace.com> |
| In reply to | #45657 |
Chris Curl <ccurl609@gmail.com> writes: > Since each unicode UTF-16 character is 2 bytes instead of 1, why > wouldn't something like this work? UTF-16 is a variable length encoding, like UTF-8. Remember there are more than a million Unicode code points. So you can't always specify one with 2 bytes. Plus as Anton says, there is the issue of composing characters: https://en.wikipedia.org/wiki/Unicode_normalization That means certain characters with diacritics have multiple encodings some of which use more than one code point, and you have to handle reversing them.
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-02-21 12:40 -0800 |
| Message-ID | <c8ba1573-77ce-49fb-a2f3-eb14a583ddc8@googlegroups.com> |
| In reply to | #45658 |
fine. no problem. but i don't have time to code it up right now. the idea is to pull each char from the source string on an auxiliary stack, starting at the beginning, parsing each char for code points. each "char" on the aux stack would have the number of bytes needed, followed by the actual bytes. 'A' would be (65 00 02 <-- TOS). a coded char would look like this: (30 03 65 00 04) or whatever. that results in a stack with the last char on the top and the first char on the bottom. then you pull the "chars" off the aux stack and build the string front to back.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2016-02-21 12:50 -0800 |
| Message-ID | <87r3g54wlg.fsf@jester.gateway.pace.com> |
| In reply to | #45659 |
Chris Curl <ccurl609@gmail.com> writes: > the idea is to pull each char from the source string on an auxiliary stack, > starting at the beginning, parsing each char for code points. Yes. For the word-reversing example, Anton posted some nice code using the data stack and RECURSE.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2016-02-21 12:56 -0800 |
| Message-ID | <87mvqt4wbd.fsf@jester.gateway.pace.com> |
| In reply to | #45659 |
Chris Curl <ccurl609@gmail.com> writes: > each "char" on the aux stack would have the number of bytes needed, > followed by the actual bytes. 'A' would be (65 00 02 <-- TOS). a coded > char would look like this: (30 03 65 00 04) or whatever. Actually you don't need that overhead. You can just build up an array in forward order, but reverse the encoded bytes for each character. So if the encoding is (30 03 64 00) then you'd write (00 64 03 30). After doing this with all the chars, you'd scan the array backwards, parsing the encodings from the reversed stream. In fact you can do this in place, with no auxiliary storage other than a few bytes to read a single encoding and reverse it.
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-02-21 14:43 -0800 |
| Message-ID | <2a2f536b-cba7-4360-97e7-2d78e425aafb@googlegroups.com> |
| In reply to | #45661 |
On Sunday, February 21, 2016 at 3:56:08 PM UTC-5, Paul Rubin wrote: > Chris Curl <ccurl...com> writes: > > each "char" on the aux stack would have the number of bytes needed, > > followed by the actual bytes. 'A' would be (65 00 02 <-- TOS). a coded > > char would look like this: (30 03 65 00 04) or whatever. > > Actually you don't need that overhead. You can just build up an array > in forward order, but reverse the encoded bytes for each character. So > if the encoding is (30 03 64 00) then you'd write (00 64 03 30). After > doing this with all the chars, you'd scan the array backwards, parsing > the encodings from the reversed stream. In fact you can do this in > place, with no auxiliary storage other than a few bytes to read a single > encoding and reverse it. The thing is ... a character may have more than one modifier, so for chars that have >1, don't you need a way to keep the char and its modifiers in the proper order? Perhaps what you are saying does that, I may just not be seeing it yet.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2016-02-21 14:59 -0800 |
| Message-ID | <87d1rp4qlo.fsf@jester.gateway.pace.com> |
| In reply to | #45664 |
Chris Curl <ccurl609@gmail.com> writes:
> The thing is ... a character may have more than one modifier, so for
> chars that have >1, don't you need a way to keep the char and its
> modifiers in the proper order? Perhaps what you are saying does that,
> I may just not be seeing it yet.
I don't think there can be unlimited numbers of modifiers, in fact
I thought there was at most 1. It doesn't matter, you can do all
the reversals in place. Algorithm:
let p = start of buffer
Until you reach the end of the buffer:
scan forward from p til you reach the end of the end of
the char including any modifiers
let q = current position
reverse the bytes in the range from p to q
let p = q
( p now points to the end of the buffer )
reverse bytes from start of buffer to p
So you've done the whole thing in place with no auxiliary buffers,
just a few temp variables for the loops and swaps.
[toc] | [prev] | [next] | [standalone]
| From | Chris Curl <ccurl609@gmail.com> |
|---|---|
| Date | 2016-02-21 16:55 -0800 |
| Message-ID | <b93f17a7-c153-4149-9485-bee859b12e0d@googlegroups.com> |
| In reply to | #45665 |
On Sunday, February 21, 2016 at 5:59:33 PM UTC-5, Paul Rubin wrote: > I don't think there can be unlimited numbers of modifiers, in fact > I thought there was at most 1. yeah, the spec says there can be more than one modifier. > It doesn't matter, you can do all > the reversals in place. Algorithm: > > let p = start of buffer > Until you reach the end of the buffer: > scan forward from p til you reach the end of the end of > the char including any modifiers > let q = current position > reverse the bytes in the range from p to q > let p = q > ( p now points to the end of the buffer ) > reverse bytes from start of buffer to p > > So you've done the whole thing in place with no auxiliary buffers, > just a few temp variables for the loops and swaps. that works ... :)
[toc] | [prev] | [next] | [standalone]
| From | Albert van der Horst <albert@spenarnc.xs4all.nl> |
|---|---|
| Date | 2016-02-22 09:37 +0000 |
| Message-ID | <56cad6d8$0$24106$e4fe514c@news.xs4all.nl> |
| In reply to | #45661 |
Paul Rubin <no.email@nospam.invalid> writes: >Chris Curl <ccurl609@gmail.com> writes: >> each "char" on the aux stack would have the number of bytes needed, >> followed by the actual bytes. 'A' would be (65 00 02 <-- TOS). a coded >> char would look like this: (30 03 65 00 04) or whatever. >Actually you don't need that overhead. You can just build up an array >in forward order, but reverse the encoded bytes for each character. So >if the encoding is (30 03 64 00) then you'd write (00 64 03 30). After >doing this with all the chars, you'd scan the array backwards, parsing >the encodings from the reversed stream. In fact you can do this in >place, with no auxiliary storage other than a few bytes to read a single >encoding and reverse it. Very nice! -- Albert van der Horst, UTRECHT,THE NETHERLANDS Economic growth -- being exponential -- ultimately falters. albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.forth
csiph-web