(this is a resend of a message that got caught in the moderation queue)
I have a friend who occasionally runs programming competitions for kids,
and when he's putting together exercises he sometimes runs them by us
just to see what we'll come up with. The other day he posted
a description of a simple task and I thought I'd have a go. I got it
working in Python very neatly, but then I decided I'd see if I could
figure out how to do the same in Factor.
Here's the problem description:
Code Golf Challenge #1
======================
Write something that will:
* Encode stdin into chunks like so:
01 1 octet SOH
xxxx 2 octets chunk number (monotonically increasing)
xx 1 octet chunk length
... <256 octets up to 255 bytes of data
xx 1 octet checksum (8-bit sum of all data bytes)
with an "end of transmission" marker of:
04 1 octet EOT
xxxx 2 octets chunk number
00 1 octet length 0
* optionally shuffle chunks
* base64-encode output
Your entry should be *readable*. Use any standard libraries you want.
Par 78 SLOC (ANSI C). It relies on standard Unix tools and pipes.
For what it's worth, I'm told this algorithm is very similar to the
ancient XMODEM file-transfer protocol. Yes, 'readable' conflicts with
'code golf'; at least for the Factor version I'm trying to prefer
readability over brevity. Also, comparing my implementation to the
sample ANSI C implementation, it turns out there are extra rules:
- chunk length is actually capped at 128 bytes
- the uint16 chunk length should be stored in big-endian order
Here's my Factor implementation. It works (that is, it produces
identical output to the reference implementation), but it's not very
pretty (note that I've ignored the 'shuffle' feature, and base64
encoding is done with an external tool, same as the reference
implementation):
USING: arrays io io.encodings io.encodings.binary kernel locals
make math pack sequences syntax ;
IN: bmodem
CONSTANT: WINDOW 128
! Splits stdin into an array of WINDOW-sized byte-arrays.
: read-chunks ( -- seq )
[ [ WINDOW read dup f = [ ] [ , t ] if ] loop ] { } make
;
! Takes a sequence of payload byte-arrays and frames each one
! with a packet-header and check-sum.
! Also adds the trailer ("EOT") packet.
: format-packets ( seq -- seq' )
[
[
[| payload index |
1 index payload length 3array "CSC" pack-be %
payload %
payload sum 256 mod ,
] B{ } make
] map-index
]
[ length 4 swap 0 3array "CSC" pack-be ] bi
suffix
;
! Slurp bytes from stdin, spit packets to stdout.
: main ( -- )
binary decode-input read-chunks
binary encode-output format-packets [ write ] each
;
MAIN: main
In particular, the way read-chunks breaks out of the loop when it's hit
EOF strikes me as ugly, what with the if word's quotations having
different stack signatures. Also, there's still a few stack-shuffling
words lurking about in there. I'm not sure if that's within standard
tolerances, or if I'm doing something wrong.
Any hints or suggestions?
------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Factor-talk mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/factor-talk