435,089 Members | 2,191 Online + Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,089 IT Pros & Developers. It's quick & easy.

String Pattern Matching algo

 P: n/a I came across a question in one of the Computing olympiad regarding string pattern matching. Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator, that prints out the decimal representation. If the decimal representation has a repeating sequence of digits, it should be indicated by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as .(3), and 41/333 = ..123123123...is denoted as .(123). Typical conversions are: 1/3 = .(3) 22/5 = 4.4 1/7 = .(142857) 3/8 = .375 45/56 = .803(571428) Now I could not think how do I even start writing a logic for creating a pattern. Then I thought that maybe I should start comparing characters from the right rather than the left. But these two examples even negate that theory; 1/7 gives me ---> 0.1428571428571428571428571429 on a 16bit machine 45/56 gives me ---> 0.8035714285714285714285714286 I was trying to eliminate the last number as it rounds off, and so I can start creating combinations from right to left. But nothing seems to be working. Any hints/suggestions will be appreciated. Apr 29 '06 #1
8 Replies

 P: n/a Correction, I meant 16 bit integer. Apr 29 '06 #2

 P: n/a 11******@gmail.com wrote: I came across a question in one of the Computing olympiad regarding string pattern matching. Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator, that prints out the decimal representation. If the decimal representation has a repeating sequence of digits, it should be indicated by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as .(3), and 41/333 = .123123123...is denoted as .(123). Now I could not think how do I even start writing a logic for creating a pattern. Algorithms questions really belong on comp.programming not here, but I'll point you in the right direction... Then I thought that maybe I should start comparing characters from the right rather than the left. But these two examples even negate that theory; 1/7 gives me ---> 0.1428571428571428571428571429 on a 16bit machine 45/56 gives me ---> 0.8035714285714285714285714286 I was trying to eliminate the last number as it rounds off, and so I can start creating combinations from right to left. But nothing seems to be working. So don't do floating point division. Any hints/suggestions will be appreciated. How about this. Start off by getting out some maths books from when you were much younger, the ones where you did long division. If you look at it, you will see you were doing repeated integer division using the remainder from the last division. Then you just have to watch out for when you start repeating yourself... -- Flash Gordon, living in interesting times. Web site - http://home.flash-gordon.me.uk/ comp.lang.c posting guidelines and intro: http://clc-wiki.net/wiki/Intro_to_clc Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php Apr 29 '06 #3

 P: n/a 11******@gmail.com wrote: I came across a question in one of the Computing olympiad regarding string pattern matching. Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator, that prints out the decimal representation. If the decimal representation has a repeating sequence of digits, it should be indicated by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as .(3), and 41/333 = .123123123...is denoted as .(123). Well you need to essentially duplicate the process of long division by hand, and note the repeating pattern like you did by hand. But the key to things like this is not to *EXACTLY* duplicate the by hand process (which has been optimized for our puny human brains), but rather rederive what makes the by hand method work, just build the relevant equations from there, and work out the process from there. A repetition when dividing a fixed point by a fixed point happens during long division when there is a repetition of the remainder *after* the last significant digit of the numerator is consumed by the division process. In long division, you are approximating x = n/d by the sequence: 10^p *(n - x_p*d) = r_p, where 0 <= r_p < d, and 10^p*x_p is an integer. If there is a p such that r_p = 0, then you have an exact division, otherwise you are looking for a pair of p's each such that 10^p > n (I think; you should check this), where r_p repeats. Should be straight forward. -- Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ Apr 29 '06 #4

 P: n/a 11******@gmail.com wrote: I came across a question in one of the Computing olympiad regarding string pattern matching. Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator, that prints out the decimal representation. If the decimal representation has a repeating sequence of digits, it should be indicated by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as .(3), and 41/333 = .123123123...is denoted as .(123). Typical conversions are: 1/3 = .(3) 22/5 = 4.4 1/7 = .(142857) 3/8 = .375 45/56 = .803(571428) Now I could not think how do I even start writing a logic for creating a pattern. Then I thought that maybe I should start comparing characters from the right rather than the left. But these two examples even negate that theory; 1/7 gives me ---> 0.1428571428571428571428571429 on a 16bit machine 45/56 gives me ---> 0.8035714285714285714285714286 I was trying to eliminate the last number as it rounds off, and so I can start creating combinations from right to left. But nothing seems to be working. Any hints/suggestions will be appreciated. Here's a hint. For a fraction in the range 0 to 1, it will be in the form .baaaa where b has k digits and a has n This number can be written as pow(10,-k)( b + a/(pow(10,n)-1)) ^^^^^^^^^^^^ (Q)This part is n nines The expression labeled with Q is all nines, so it has no factors which are 2 or 5. In your rational expression N/D collect the factors of 2 and 5, so D = pow(2,r) * pow(5,s) * R k must be the larger of r and s, and n (number of nines in Q) will be at most R and could be less. b has at most than k digits. Notice that 16-bit signed numbers can reach pow(2,15)-1 == 32767. Luckily this is not prime, but there are lots of prime numbers nearby. For example, 32749 is prime. Be prepared to handle repeating digits of at least this size. The above discussion should tell you thar 1/3 has no leading decimals before the repeating segment, and 1/6 has 1 (since 6 = pow(2,1)*pow(5,0)*3) . So 1/3 is pow(10,0) * (3/9) where 3 is 'a', the repeating. Because k == 0, the nonrepeating intial sequence has no digits (so is not even shown as a zero), abd 1/6 is pow(10,-1) * (1 + 6/9). The nonrepeating section b is one digit (since k = 1) and the repeating segment is a 6. Note that we did not use denominators of 3 or 6 nines. We nneded the smallest number of the form pow(10,n)-1 with 3 as a factor. That number is 9, with a single digit. 1/7 has 7 digits in the repeating string, because 9999999 is the smallest such number with 7 for a factor. So here's the strategy. If the fraction is improper (N >= D) remove the integgal part and write it: I. (so N/D = I + N'/D with a proper fraction) otherwise write 0, Factor out the 2's and 5's in D. The larger index tells us how many digits are in the non-repeating segment. Compute it and write it down. I.b The residual D', D with all the factors 2 and 5, either must be 1 (so I.b us terminating, a = 0, and we'ew done) our must divide a number of the form 9....9 of 1 to D' digits. Start with Q=9, Q = 10*Q+9, etc until you have one or have reached the timits of your machine. This part need not be reported and may be done with, say, unsigned long long ints even if the problem space is for signed ints. This rells you n, the length the repeating string. Wrete the '(', generate the n digits, write down a ')': I.a(b) Apr 30 '06 #5

 P: n/a <11******@gmail.com> wrote in message news:11**********************@y43g2000cwc.googlegr oups.com... I came across a question in one of the Computing olympiad regarding string pattern matching. Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator, that prints out the decimal representation. If the decimal representation has a repeating sequence of digits, it should be indicated by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as .(3), and 41/333 = .123123123...is denoted as .(123). Typical conversions are: 1/3 = .(3) 22/5 = 4.4 1/7 = .(142857) 3/8 = .375 45/56 = .803(571428) Now I could not think how do I even start writing a logic for creating a pattern. IIRC, there is a recursive algorithm (using 1/X ?) to convert terminated (non-repeating and not random values PI, etc.) decimals to the form N/D. If so (and since they gave you a valid fraction), you could compute N/D as decimal and then attempt to convert back to N/D. If the number is non-repeating, the first N and D should be the same as the second conversion N and D. If the number is repeating, it will be terminated by the precision of the machine. This means that the first N and D will be different from the conversion N and D, because it lost some precision. For the repeating numbers, you then need to determine the length of the repeat. I don't know if there is a simple method for that. Rod Pemberton Apr 30 '06 #6

 P: n/a "Rod Pemberton" wrote in message news:e3**********@emma.aioe.org... <11******@gmail.com> wrote in message news:11**********************@y43g2000cwc.googlegr oups.com... I came across a question in one of the Computing olympiad regarding string pattern matching. Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator, that prints out the decimal representation. If the decimal representation has a repeating sequence of digits, it should be indicated by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as .(3), and 41/333 = .123123123...is denoted as .(123). Typical conversions are: 1/3 = .(3) 22/5 = 4.4 1/7 = .(142857) 3/8 = .375 45/56 = .803(571428) Now I could not think how do I even start writing a logic for creating a pattern. IIRC, there is a recursive algorithm (using 1/X ?) to convert terminated (non-repeating and not random values PI, etc.) decimals to the form N/D. If so (and since they gave you a valid fraction), you could compute N/D as decimal and then attempt to convert back to N/D. If the number is non-repeating, the first N and D should be the same as the second conversion N and D. If the number is repeating, it will be terminated by the precision of the machine. This means that the first N and D will be different from the conversion N and D, because it lost some precision. For the repeating numbers, you then need to determine the length of the repeat. I don't know if there is a simple method for that. I should probably clarify slightly. The algorithm will need be modified to continue conversion until it's base is equal to or near D. This of course will eliminate problems like 32/16 being returned as 2/1. RP Apr 30 '06 #7

 P: n/a Martin Ambuhl wrote a bunch of stuff): But note that the method for determining the number of repeating digits The residual D', D with all the factors 2 and 5, either must be 1 (so I.b us terminating, a = 0, and we'ew done) our must divide a number of the form 9....9 of 1 to D' digits. Start with Q=9, Q = 10*Q+9, etc until you have one or have reached the timits of your machine. This part need not be reported and may be done with, say, unsigned long long ints even if the problem space is for signed ints. This rells you n, the length the repeating string. is not perhaps not very useful after all, the largest values for Q are 16 bits (signed or unsigned) 9999 (so D' <= 4: specifically 3, but 3 divides 9) 32 bits (signed or unsigned) 999999999 (do D' <= 9: 3,7,9, but 3 and 9 divide nine, only 7 is useful) 64 bits (signed) 999999999999999999 (so D' <= 18; picking up 11, 13, 17) 64 bits (unsigned) 9999999999999999999 (so D' <= 19; 19) So whats the point? After reporting I. (the integral part), computing k (the length of the non-repeating segment) and reporting the k digits and the opening brace, now showing I.b(, you know that the repeating string is at most n characters. There are strategies for storing generated digits un either one or two allocated buffers of n chars each. The two buufer approach may well win on speed; the one buffer approach on space. Once you have the n chars (or in the two buffer case, well before then) you can easily for repetitions the initial part of the n-digit repeating pattern, yielding a shorter one? And you don't need to check all lengths. Contemplate what the prime factors of D' tell you about what lengths make sense. And I forgot to note, that if you don't 1) reduce N/D, eliminating common factors and 2) if exactly one of N or D is negative, report a '-'. if any of N or D is negative, change its sign. 3) if D is zero, report the fact and quit then all bets are off. Apr 30 '06 #8

 P: n/a On 29 Apr 2006 13:52:28 -0700, "11******@gmail.com" <11******@gmail.com> wrote: I came across a question in one of the Computing olympiad regardingstring pattern matching.Write a program that will accept a fraction of the form N/D, where N isthe numerator and D is the denominator, that prints out the decimalrepresentation. If the decimal representation has a repeating sequenceof digits, it should be indicated by enclosing it in brackets. Forexample, 1/3 = .33333333...is denoted as .(3), and 41/333 =.123123123...is denoted as .(123).Typical conversions are:1/3 = .(3)22/5 = 4.41/7 = .(142857)3/8 = .37545/56 = .803(571428)Now I could not think how do I even start writing a logic for creatinga pattern.Then I thought that maybe I should start comparing characters from theright rather than the left.But these two examples even negate that theory;1/7 gives me ---> 0.1428571428571428571428571429 on a 16bit machine45/56 gives me ---> 0.8035714285714285714285714286I was trying to eliminate the last number as it rounds off, and so Ican start creating combinations from right to left. But nothing seemsto be working.Any hints/suggestions will be appreciated. Somewhere in the depths of number theory remembrances, I recall a method of determining when the repetition starts and the length of the repetition. Unfortunately, the details have long been forgotten. Attempting to compare digits is error prone because if you see a value of .121212 you might conclude the answer is .(12) when the answer really is .(1212121212123). This is really more an algorithm question rather than C. Remove del for email Apr 30 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion. 