9
\$\begingroup\$

Create a program which takes one command-line argument, n, which will be an integer less than 2147483648 (2^31), and then reads a file input.txt and prints the lines of input.txt which contain any substring which is a positive (non-zero) multiple of n. You may choose to ignore multiples greater than 2147483647.

Test case

If input.txt contains

1. Delaware Dec. 7, 1787    
2. Pennsylvania Dec. 12, 1787   1682
3. New Jersey   Dec. 18, 1787   1660
4. Georgia  Jan. 2, 1788    1733
5. Connecticut  Jan. 9, 1788    1634
6. Massachusetts    Feb. 6, 1788    1620
7. Maryland Apr. 28, 1788   1634
8. South Carolina   May 23, 1788    1670
9. New Hampshire    June 21, 1788   1623
10. Virginia    June 25, 1788   1607
11. New York    July 26, 1788   1614
12. North Carolina  Nov. 21, 1789   1660
13. Rhode Island    May 29, 1790    1636
14. Vermont Mar. 4, 1791    1724
15. Kentucky    June 1, 1792    1774
16. Tennessee   June 1, 1796    1769
17. Ohio    Mar. 1, 1803    1788
18. Louisiana   Apr. 30, 1812   1699
19. Indiana Dec. 11, 1816   1733
20. Mississippi Dec. 10, 1817   1699
21. Illinois    Dec. 3, 1818    1720
22. Alabama Dec. 14, 1819   1702
23. Maine   Mar. 15, 1820   1624
24. Missouri    Aug. 10, 1821   1735
25. Arkansas    June 15, 1836   1686
26. Michigan    Jan. 26, 1837   1668
27. Florida Mar. 3, 1845    1565
28. Texas   Dec. 29, 1845   1682
29. Iowa    Dec. 28, 1846   1788
30. Wisconsin   May 29, 1848    1766
31. California  Sept. 9, 1850   1769
32. Minnesota   May 11, 1858    1805
33. Oregon  Feb. 14, 1859   1811
34. Kansas  Jan. 29, 1861   1727
35. West Virginia   June 20, 1863   1727
36. Nevada  Oct. 31, 1864   1849
37. Nebraska    Mar. 1, 1867    1823
38. Colorado    Aug. 1, 1876    1858
39. North Dakota    Nov. 2, 1889    1812
40. South Dakota    Nov. 2, 1889    1859
41. Montana Nov. 8, 1889    1809
42. Washington  Nov. 11, 1889   1811
43. Idaho   July 3, 1890    1842
44. Wyoming July 10, 1890   1834
45. Utah    Jan. 4, 1896    1847
46. Oklahoma    Nov. 16, 1907   1889
47. New Mexico  Jan. 6, 1912    1610
48. Arizona Feb. 14, 1912   1776
49. Alaska  Jan. 3, 1959    1784
50. Hawaii  Aug. 21, 1959   1820

then find_multiples 4 will print the entire file, and find_multiples 40 will print

10. Virginia    June 25, 1788   1607
17. Ohio    Mar. 1, 1803    1788
21. Illinois    Dec. 3, 1818    1720
32. Minnesota   May 11, 1858    1805
40. South Dakota    Nov. 2, 1889    1859
41. Montana Nov. 8, 1889    1809
\$\endgroup\$
4
  • \$\begingroup\$ 1. Are you sure you mean 32 bytes and not 32 bits? 2. What multiple of 4 is present in the line 33. Oregon Feb. 14, 1859 1811? Is it the 4 in 14, implying that the match is against any substring rather than any string of digits delimited by non-digits or end of line? \$\endgroup\$ Jul 3, 2013 at 22:00
  • \$\begingroup\$ yes the 4 in 4 counts as a 4 because it is a substring. \$\endgroup\$
    – ojblass
    Jul 3, 2013 at 22:03
  • 3
    \$\begingroup\$ Also, is this code golf or does it have some other winning criterion? \$\endgroup\$ Jul 3, 2013 at 23:06
  • \$\begingroup\$ just code golf... sorry just learning here! \$\endgroup\$
    – ojblass
    Jul 10, 2013 at 17:19

4 Answers 4

4
\$\begingroup\$

Perl, 67 chars

open F,"input.txt";print grep/(\d+)(?(?{!$^N+$^N%$ARGV[0]})(*F))/,<F>

Please note that the given character count is taking advantage of one of Perl's more horrific features, namely that a special variable of the form $^X can be written in two characters instead of three, by replacing the ^X with a literal ctrl-X character.

And, of course, this solution wouldn't be possible without a couple of Perl's arguably-equally-terrifying regex extensions that allows one to embed actual code inside of a regex pattern. (But at least those features are clearly documented as being potentially scary.)

[EDITED to fix bug in argument-handling due to not reading the description carefully enough.]

\$\endgroup\$
2
  • \$\begingroup\$ As I can see the solution doesn't read from file input.txt. \$\endgroup\$
    – Howard
    Jul 4, 2013 at 7:47
  • \$\begingroup\$ Hm. As I read it, the problem description states that the program takes two arguments, the name of the input file and the number to search for multiples of. I see now that this is modified at the very end of the description. Nice little trap you set for me there, Oscar Blass. \$\endgroup\$
    – breadbox
    Jul 4, 2013 at 7:52
2
\$\begingroup\$

Mathematica

dates=Import["input.txt"]
f[digits_]:=FromDigits/@Flatten[Table[Partition[digits,k,1],{k,1,Length[digits]}],1]
g[oneline_]:={FromDigits[oneline[[1]]],Complement[Union[Flatten[f/@oneline]],{0}]}
h[n_,{a_,b_}]:={a,MemberQ[Mod[#,n]&/@b,0]};

w[k_]:=Column@dates[[Cases[h[k,g[#]]&/@ToExpression@(Characters /@ (StringCases[#, DigitCharacter ..] & /@ dates)),{j_,True}:>j]]]

f removes all non-digits;

g finds all the numbers that can be found in a single date line.

h checks to see whether Mod[x, n] is true for any of the numbers returned by g.

w calls the subroutines and formats the output.

Examples

n=40
w[n]

output 40


 n=51
 w[n]

output 51


 n=71
 w[n]

output 71

\$\endgroup\$
5
  • \$\begingroup\$ It returns "ToExpression::sntx: Invalid syntax in or before "1. Delaware Dec. 7, 1787 "." to me \$\endgroup\$ Jul 5, 2013 at 18:01
  • \$\begingroup\$ @belisarius I suspect that there was a problem with your "Input.txt" file. Try directly setting dates={"1. Delaware Dec.7,1787"} Then try w[17]. It should return the same line of information. \$\endgroup\$
    – DavidC
    Jul 5, 2013 at 20:03
  • \$\begingroup\$ Ok. How should I save my input file? \$\endgroup\$ Jul 5, 2013 at 21:15
  • \$\begingroup\$ First put your data into a list: dates = {"1. Delaware Dec.7,1787",...}, then Export["input.txt",dates]. You use Import["input.txt", dates] to get it back. \$\endgroup\$
    – DavidC
    Jul 5, 2013 at 22:17
  • \$\begingroup\$ Ahh ... OK. Some massaging was needed. Thanks! \$\endgroup\$ Jul 5, 2013 at 23:17
2
\$\begingroup\$

Q, 94

-1@m(&){0|/{(x>0)&0=x mod"I"$.z.x 0}"J"$sublist[;x]'[a cross a:(!)1+(#)x]}'[m:(0:)`input.txt];

There's undoubtedly a more graceful way to find substrings in q.

$ q find_multiples.q 40 -q
10. Virginia    June 25, 1788   1607
17. Ohio    Mar. 1, 1803    1788
21. Illinois    Dec. 3, 1818    1720
32. Minnesota   May 11, 1858    1805
40. South Dakota    Nov. 2, 1889    1859
41. Montana Nov. 8, 1889    1809

.

$ q find_multiples.q 51 -q
19. Indiana Dec. 11, 1816   1733
25. Arkansas    June 15, 1836   1686
37. Nebraska    Mar. 1, 1867    1823
\$\endgroup\$
2
\$\begingroup\$

Ruby 2.0, 129 chars

With some help from @chron:

IO.foreach('input.txt'){$><<$_ if$_.gsub(/\d+/).any?{(0..s=$&.size).any?{|i|(1..s).any?{|j|(v=$&[i,j].to_i)%$*[0].to_i<1&&v>0}}}}

That long line broken up a bit:

IO.foreach('input.txt') {
    $> << $_ if $_.gsub(/\d+/).any? {
        (0..s=$&.size).any? { |i|
            (1..s).any? { |j|
                (v=$&[i,j].to_i) % $*[0].to_i < 1 && v>0 }}}}

Example:

$ ruby july4.rb 40
10. Virginia    June 25, 1788   1607
17. Ohio    Mar. 1, 1803    1788
21. Illinois    Dec. 3, 1818    1720
32. Minnesota   May 11, 1858    1805
40. South Dakota    Nov. 2, 1889    1859
41. Montana Nov. 8, 1889    1809

$ ruby july4.rb 71
29. Iowa    Dec. 28, 1846   1788
\$\endgroup\$
4
  • 2
    \$\begingroup\$ A few small savings for the second line: IO.foreach('input.txt'){|l|puts l if l.scan(/\d+/).any?{|a|(0..s=a.size).any?{|i|(1..s).any?{|j|(v=a[i,j].to_i)%n<1&&v>0}}}} I love #combination but it's such a long word! \$\endgroup\$ Jul 4, 2013 at 6:07
  • \$\begingroup\$ Thanks chron! Yes, semantically, I think my original answer was prettier, but this is way shorter; Nice one! I managed to sqeeze out a few more chars by taking advantage of some $variables, so now it almost looks like perl! \$\endgroup\$
    – daniero
    Jul 4, 2013 at 9:12
  • \$\begingroup\$ Looks good! Looking at the spec again, apparently n needs to be a command-line arg rather than a value read from stdin. So you could delete your first line entirely and replace n in the second line with $*[0].to_i \$\endgroup\$ Jul 4, 2013 at 22:46
  • \$\begingroup\$ Right you are! thanks. \$\endgroup\$
    – daniero
    Jul 5, 2013 at 6:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.