test-check

murtaza 2021-03-04T21:18:05.004800Z

What's a nice way to generate pairs of strings that differ by n characters? All my efforts so far have led to me baking in a ton of logic into fmaps. Does anyone have any suggestions about how I can do this by putting non-custom generators together?

2021-03-04T21:21:32.009100Z

it seems unlikely, but I think you should be able to get by with a single fmap

2021-03-04T21:22:23.010300Z

Equal length strings?

2021-03-04T21:24:13.012100Z

generate a string of more than n characters, generate a vector of n characters and indices, then fmap over both of those producing a pair of the string, and the string with characters swapped at the indices

2021-03-04T21:24:56.012700Z

(the indices will require some fiddling to work out right, but doable)

2021-03-04T21:25:05.013Z

You could also generate edit operations

2021-03-04T21:25:35.013400Z

yeah, characters + indices are an edit operation

murtaza 2021-03-04T21:27:35.015500Z

What I've done so far is generate a string, and then edit out parts of it at random start and end positions using subs, joins and replace

2021-03-04T21:27:35.015600Z

no, I don't think you can do it without an fmap

2021-03-04T21:28:20.016800Z

Random meaning calling rand-int or similar?

2021-03-04T21:28:27.017200Z

in order for the generator to work at all, you need to at the base to be able to turn 1 string in to a pair of strings

2021-03-04T21:28:42.017800Z

that is gonna be an fmap

murtaza 2021-03-04T21:30:22.018900Z

choose with a range based on the count of characters in the string

2021-03-04T21:34:03.019400Z

Tied together with bind and fmap?

murtaza 2021-03-04T21:35:34.019600Z

Yup. I've thrown the code away and it's no longer in my undo tree unfortunately.

2021-03-04T21:35:46.019800Z

Ha

murtaza 2021-03-04T21:36:33.020Z

let instead of bind.

2021-03-04T21:38:50.020200Z

Sure

2021-03-04T21:39:34.021300Z

I think generating edits is pretty easy, though it might be harder to aim for exactly N differences if you need that

2021-03-04T21:39:54.021700Z

Generating edits would shrink nicely I think

2021-03-04T21:40:07.022200Z

If you want to shrink toward fewer differences

murtaza 2021-03-04T21:42:17.023700Z

I'll give it a shot in the AM and report

2021-03-04T21:51:32.024600Z

;; written but not run
;; assuming strings of length 5 and differences of 3 characters
(gen/fmap
 (fn [string edits]
   (loop [[[shift index] & es] edits
          s (vec string)
          editted #{}]
     (if e
       (let [i (mod index (count s))]
         (if (contains? editted i)
           (recur (cons [shift (inc index)] es) s editted)
           (recur es
                  (update-in s [i] (fn [c]
                                     (char (+ 32 (mod (+ offset (- (int c) 32)) 126)))))
                  (conj editted i))))
       (apply str s))))
 (gen/tuple (gen/resize 5 gen/string-ascii)
            (gen/tuple
             (gen/tuple s-pos-int s-pos-int)
             (gen/tuple s-pos-int s-pos-int)
             (gen/tuple s-pos-int s-pos-int))))

2021-03-04T21:56:50.025Z

(that mod 126 should maybe be mod 126 - 32)

2021-03-04T21:57:26.025300Z

and the fn has to destructure the vector, etc

robertfw 2021-03-04T21:58:07.025800Z

Can you recur from there?

2021-03-04T21:58:24.026Z

inside a loop? of course

robertfw 2021-03-04T21:58:52.026500Z

I meant from non-tail position

2021-03-04T21:59:08.026700Z

I am pretty sure those are all tails

robertfw 2021-03-04T22:00:25.027900Z

I thought I had run into not being able to recur from the first branch of if but I may well be getting mixed up with recur within try

2021-03-04T22:01:51.028900Z

yes, you can't recur across a try, logically a try pushes an exception handler on to a stack, so recuring across a try grows the exception handling stack

robertfw 2021-03-04T22:03:40.029200Z

Thanks, that makes sense