factor: Simple tools are fun

After more than a year and a half of tinkering with random console programs, I know enough to look forward to fun stuff out of coreutils. Here’s factor, which I admit has almost no explicit function beyond showing the prime factorization of a number.

kmandla@6m47421: ~$ factor 120
120: 2 2 2 3 5

Which is absolutely correct, of course: 2x3x4x5 does in fact equal 120, and factor is nice enough to group similar factors for readability.

But that’s all it does. So what’s the big deal, K.Mandla?

Well, aside from fulfilling my desire to see simple, straightforward, light but functional software, factor has potential. My only real concession to factor is that I’d prefer I had a count of how many of each factor there were, rather than just a string of factors. That would mean factor 65536 would appear as

65336:
16x2

rather than just a string of 16 number 2s. Call me picky.

First let’s lose the colon-plus-space arrangement, and kick in a tab character instead, for reasons that will be clear in a moment. sed can help with that.

factor 720 | sed -e 's/: /\t/g'

I’d prefer a tab character there only because cut likes tab characters as delimiters.

factor 720 | sed -e 's/: /\t/g' | cut -f2

Now we just need to break off each number where a space appears, and we can call in some heavyweights. sed again, just for kicks.

factor 720 | sed -e 's/: /\t/g' | cut -f2 | sed -e 's/ /\n/g'

Now we go medieval. Remember uniq? Watch this:

factor 720 | sed -e 's/: /\t/g' | cut -f2 | sed -e 's/ /\n/g' | uniq -c

Four twos, two threes and a five. Yup, that’s right. That’s 720. uniq counted the lines and gave a total. Too much whitespace at the front though.

factor 720 | sed -e 's/: /\t/g' | cut -f2 | sed -e 's/ /\n/g' | uniq -c | sed -e 's/^[ ]*//g'

And it would be nice if there was just a multiplier mark between the count and the factor.

kmandla@6m47421: ~$ factor 720 | sed -e 's/: /\t/g' | cut -f2 | sed -e 's/ /\n/g' | uniq -c | sed -e 's/^[ ]*//g' | sed -e 's/ /x/g'
4x2
2x3
1x5

Close enough for government work. From there we would only need to prefix the output with the number, like I showed above. If you stick this in a loop, it becomes even more interesting. Try

for i in {2..99} ; do echo $i':' ; factor $i | sed -e 's/: /\t/g' | cut -f2 | sed -e 's/ /\n/g' | uniq -c | sed -e 's/^[ ]*//g' | sed -e 's/ /x/g' ; echo ; done

for more complete (replete?) results.

What’s the point in all this? Not much of one, that I can see. This wasn’t meant to be some sort of lesson on sed and uniq; suffice to say I have plans for that particular loop that are … beyond the focus of this blog. Feel free to adjust it to your own nefarious plans.😉

4 thoughts on “factor: Simple tools are fun

  1. ids1024

    Use awk to simplify (well, shorten and speed up anyway) your code:
    for i in {2..99} ; do echo $i: ; factor $i | awk ‘BEGIN{RS=” “;OFS=”x”}NR>1{c[$1]++}END{for (i in c)print c[i],i}’ ; echo ; done

    1. K.Mandla Post author

      Yes, awk is really the way to go with something like this. My awk skills are only slightly worse than my bash skills though, so I’d only be losing ground by suggesting something in awk. Thanks for the solution!😀

      1. ids1024

        I don’t have much experience with awk either; that line required a bit of googling. Also note that two sed commands can be combined with a semicolon:
        sed -e ‘s/^[ ]*//g;s/ /x/g’

      2. K.Mandla Post author

        True again, and in the script I kept for my off-topic project, I used a semicolon. I just wanted to be able to step through the command, for illustration’s sake. Thanks!😉

Comments are closed.