Reverse-Engineering a single-wire bus protocol - reverse-engineering
We are currently reverse-engineering our HAC systems (Heating+Air-Conditioning but no Ventilations. Mitsubishi Heavy Industries FDTCA.) one-wire bus protocol since our HAC units do not heat correctly anymore. We assume faulty control-units and temp-sensors. Our distributor and installer can not provide new control-units and we have not found any aftermarket solutions that support the FDTCA.
Things we have learned so far:
12V Bus
One-Wire Multi-Drop
Master-Slave-Slave
Periodic communication: Control panel sends x bits, outdoor-unit sends x bits, indoor-unit sends x bits
Does not seem to be a ping-pong communication but rather just a dump of values by every unit, initiated by the dump of the control panel (master)
Seems to communicate at somewhere between 1000baud and 1500baud.
Driven with an LM2904
The CPU of the control panel seems to be a proprietary NEC processor (NEC 606 0720KP010)
This is a screenshot of one interval of the communication. The first packet is send by the control panel, the second and third either by the indoor- or the outdoor-unit. If we disconnect the bus from the control panel, it deliberately sends data and increases the interval of its dump seemingly because it does not receive a dump from the other units.
Whole Communcation:
First Packet:
(Data of this trace available as 60M CSV.)
We already tried some default UART configurations (i.E. 9600baud, 8N1, 9N1, etc) but had no luck decoding the data.
We are a bit clueless on how we should proceed reverse-engineering the encoding. One non-educated guess was that it could be something like an ISO 9141 inspired encoding.
We do not need any help in decoding the "payload", but rather make sense of the actual encoding on the wire.
Any hints or info about protocols/encodings that match the 12V, 1-Wire and 9 to 11kbaud spec would be much appreciated.
Update:
I hooked up our last spare panel in one of our working HAC system for an Master-Panel, Slave-Panel, Outdoor-Unit, Indoor-Unit system. Now there are 5 frames on the bus.
Then I observed the frames behind the op-amp where TX and RX are two separate wires on the Slave-Panel. This panel sends the second frame on the bus. Its payload is very similar with the first frame and only differs by its last 2 bytes and the 2nd one. The last 2 bytes seem to be some kind of checksum, the first two byte seem to be some kind of device-id or addressing. The slave panel alters its payload to be identical to the payload of the first frame. As soon as the first frame changes, the 2nd frame (the one send by the slave) mirrors the changes.
Next I quickly hacked together a decoder (1 = low, 0 = high) which decodes the data on the bus to a simple binary representation. The following code-block is a dump of 3 rounds of 5 frames:
B: 11011001 10010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00101010
B: 11011001 01010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00101100
B: 11011111 10010000 11100011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00100110
B: 11011111 01010110 11100011 10100101 01011100 10101110 00101111 11111000 00010101 10101011 11111111 01111110 00001111 00000001 00000000 10100000 00010110 11111010 10111111 10010000 00001010 01000101
B: 10011011 10010000 00100011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101011 10000001 00010000 00100000 00010100 01011000
B: 11011001 10010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00101010
B: 11011001 01010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00101100
B: 11011111 10010000 11100011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00100110
B: 11011111 01010110 11100011 10100101 01011100 10101110 00101101 11111000 00110101 10101011 11111111 01111110 00001111 00000001 00000000 10100000 00010110 11111010 10111111 10010000 00001010 01000101
B: 11101011 11010000 11100011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101011 10000001 00010000 00100000 00010111 10100100
B: 11011001 10010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00101010
B: 11011001 01010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00101100
B: 11011111 10010000 11100011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101000 00000101 00000000 10100000 00010111 00100110
B: 11011111 01010110 11100011 10100101 01011100 10101110 00111111 11111000 00010101 10101011 11111111 01111110 00001111 00000001 00000000 10100000 00010110 11111010 10111111 10010000 00001010 01000101
B: 11101011 11010000 01101011 10100101 01011100 10101110 00101101 10110000 00100000 00010100 00000010 11111000 01010000 00001010 00000111 01000000 00101011 10000001 00010000 00100000 00010111 10000110
I ruled out any "start-bit" or "stop-bits": There are no repeating patterns in 1's or 0's. Only the first bit of a frame seems to be a stable 1.
I observed byte 6 and 7 to be related to the temperature, byte 8 and 9 to the fanspeed and byte 5 for the louver (one bit for automatic, 2 additional bits for the manual mode).
The bits are shown exactly like they are ordered on the bus.
I mapped out all selectable temperatures (16-30°C) in a table:
°C Byte 6 Byte 7
16 10101110 11101101
17 10101100 11101001
18 10101111 01101101
19 10101101 01101001
20 10101110 01101001
21 10101100 01101101
22 10101111 10101101
23 10101101 10101001
24 10101110 10101001
25 10101100 10101101
26 10101111 00101001
27 10101101 00101101
28 10101110 00101101
29 10101100 00101001
30 10101111 11001101
But I had no luck in parsing them to something that makes sense. Only the last two bits of byte 6 and the 6 first bits of byte 7 seem to be related to the temperature, but regardless on how I join them together and read them as LSB or MSB, they result in no meaningful numbers.
Only the louver-bits seem to have a meaningful pattern.
Technically I could do some "replay-attacks" on the bus as a slave to control the devices, but for this I would have to figure out the checksum in the last two bytes.
start: edit by virolino
I hacked the temperatures table a little bit. I removed the non-changing bits, and grouped the temperatures, and I extended the table according to the pattern I noticed.
°C 1 2 3 4
00 10 11 01 11
01 00 11 01 10
02 11 01 01 11
03 01 01 01 10
04 10 01 01 10
05 00 01 01 11
06 11 10 01 11
07 01 10 01 10
08 10 10 01 10
09 00 10 01 11
10 11 00 01 10
11 01 00 01 11
12 10 00 01 11
13 00 00 01 10
14 11 11 10 10
15 01 11 10 11
16 10 11 10 11
17 00 11 10 10
18 11 01 10 11
19 01 01 10 10
20 10 01 10 10
21 00 01 10 11
22 11 10 10 11
23 01 10 10 10
24 10 10 10 10
25 00 10 10 11
26 11 00 10 10
27 01 00 10 11
28 10 00 10 11
29 00 00 10 10
30 11 11 00 11
31 01 11 00 10
32 10 11 00 10
33 00 11 00 11
Sequence 11 01 10 00 seems to be the key. It changes for every temperature on column 1, it is constant for 4 temperatures on column 2 and is constant for 16 temperatures on column 3. There are 2 endings on column 4: 11 10 10 11 (twice) and 10 11 11 10 (twice) and then it repeats. Except that for temperature 30, column 4 breaks the rule :(
Another rule break: col. 3 of temperature 30 is 00 instead of 11 :(
So it seems that col. 3 is a kind of MSB, col 2 is a mid-SB and col. 1 is a LSB.
end: edit by virolino
I have only a clue on the temps, not an answer. It's too hard to write in comments.
Possible:
Temperatures are 4 bits with a bias of 14.
Invert all the bits: active lo.
Byte 6, last two bits are bits 0 and 1 of the temp.
Byte 7, first two bits are bits 2 and 3.
The careful biasing and packing seem to say that the prefix and suffix bits are other data fields. Sigh... The rest could be a tough or impossible job unless you can decompile hardware or firmware.
Here's a program for fiddling:
def fiddle():
x = [
(16, '10101110', '11101101'),
(17, '10101100', '11101001'),
(18, '10101111', '01101101'),
(19, '10101101', '01101001'),
(20, '10101110', '01101001'),
(21, '10101100', '01101101'),
(22, '10101111', '10101101'),
(23, '10101101', '10101001'),
(24, '10101110', '10101001'),
(25, '10101100', '10101101'),
(26, '10101111', '00101001'),
(27, '10101101', '00101101'),
(28, '10101110', '00101101'),
(29, '10101100', '00101001'),
(30, '10101111', '11001101'),
]
swap01 = str.maketrans({'0': '1', '1': '0'})
for t in x:
b1 = t[1][6:][::-1]
b2 = t[2][:3][::-1]
ib1 = b1.translate(swap01)
ib2 = b2.translate(swap01)
val = int(b1 + b2, 2)
rval = int(b2 + b1, 2)
ival = int(ib1 + ib2, 2)
irval = int(ib2 + ib1, 2)
print(f'{t[0]}: ib1={int(ib1, 2)} ib2={int(ib2, 2)} irval={irval} biased={irval + 14}')
fiddle()
Prints:
16: ib1=2 ib2=0 irval=2 biased=16
17: ib1=3 ib2=0 irval=3 biased=17
18: ib1=0 ib2=1 irval=4 biased=18
19: ib1=1 ib2=1 irval=5 biased=19
20: ib1=2 ib2=1 irval=6 biased=20
21: ib1=3 ib2=1 irval=7 biased=21
22: ib1=0 ib2=2 irval=8 biased=22
23: ib1=1 ib2=2 irval=9 biased=23
24: ib1=2 ib2=2 irval=10 biased=24
25: ib1=3 ib2=2 irval=11 biased=25
26: ib1=0 ib2=3 irval=12 biased=26
27: ib1=1 ib2=3 irval=13 biased=27
28: ib1=2 ib2=3 irval=14 biased=28
29: ib1=3 ib2=3 irval=15 biased=29
30: ib1=0 ib2=4 irval=16 biased=30
Related
How do you compress image data for LZW encoding for .GIF files?
I am having trouble understanding how to compress image data for the 89a specification for .gif files. Say for example I am trying to make a 3x2 .GIF. Let me construct a sample color code table and walk through an example [of what I think is correct]. Color code | Color ------------------ 0 | Brown 1 | Red 2 | Green 3 | Black The image I want to create is this. 3x2 pixels (6 pixels total) ---------- Br Br Br Br R Br Compressing with LZW walks me through this process. This is the final code table I get. Code table ---------- # | code 0 | 0 1 | 1 2 | 2 3 | 3 4 | clear 5 | eoi // end of information 6 | 0 0 7 | 0 0 0 8 | 0 1 9 | 1 0 With an eventual value of 4 0 6 0 1 0 5 that are my codes. Because I wrote out a code 0 0 0, this code value equals 7, so I had to increase my code size from 3 > 4 bits for subsequent codes. So, here are the bytes of my image data (from my code table). 100 - 4 000 - 0 110 - 6 0000 - 0 0001 - 1 0000 - 0 0101 - 5 I end up encoding my image data as 10000100 - 132 00100001 - 33 10100000 - 160 00000000 - 0 Which ends up looking like this in my final .gif file (I've put brackets around the values that correspond to the image data) 47 49 46 38 39 61 03 00 02 00 f1 00 00 b9 7a 56 ff 00 00 00 ff 00 00 00 00 21 ff 0b 4e 45 54 53 43 41 50 45 32 2e 30 03 01 ff ff 00 21 f9 04 04 64 00 00 00 2c 00 00 00 00 03 00 02 00 00 [02 04 84 21 a0 00 00] 3b // Explanation 02 - Minimum LZW code size 04 - Data sub-block of 4 bytes 84 - 132 in decimal 21 - 33 in decimal a0 - 160 in decimal 00 - 0 in decimal 00 - Termination byte My image looks something like this (why is there green in here instead of red?). I blew the image up since 2x3 pixels is a bit hard to read. Is there something fundamental that I am missing? I appreciate your time to look at this with me.
Found the error, it lies in the code size when compressing LZW image data. When you are creating the code table when compressing image data with LZW, you need to increment your code size when you've added a code that equals to 2^(code size). So, instead of incrementing the code size by one after adding code 7 | 0 0 0 (as shown in the table above), I needed to instead increment the code size by one after adding 8 | 0 1 (because 8 = 2^(code size == 3)). This is how the image data changes by incrementing the code size as described 100 - 4 000 - 0 110 - 6 000 - 0 0001 - 1 0000 - 0 0101 - 5 And then, how the resulting image data bytes has changed. 10000100 - 132 00010001 - 17 01010000 - 80 I've put brackets around the data to show a comparison from the full .gif data to show what has changed (after applying the fix). This is the same .gif file from above. 47 49 46 38 39 61 03 00 02 00 f1 00 00 b9 7a 56 ff 00 00 00 ff 00 00 00 00 21 ff 0b 4e 45 54 53 43 41 50 45 32 2e 30 03 01 ff ff 00 21 f9 04 04 64 00 00 00 2c 00 00 00 00 03 00 02 00 00 [02 03 84 11 50 00] 3b // Explanation 02 - Minimum LZW code size 03 - Data sub-block of 3 bytes 84 - 132 in decimal 11 - 17 in decimal 50 - 80 in decimal 00 - Termination byte
haskell tls file to list of list
I have a tls file such as: 1224 926 1380 688 845 109 118 88 1275 1306 91 796 102 1361 27 995 1928 2097 138 1824 198 117 1532 2000 1478 539 1982 125 1856 139 475 1338 848 202 1116 791 1114 236 183 186 150 1016 1258 84 952 1202 988 866 946 155 210 980 896 875 925 613 209 746 147 170 577 942 475 850 1500 322 43 95 74 210 1817 1631 1762 128 181 716 171 1740 145 1123 3074 827 117 2509 161 206 2739 253 2884 248 3307 2760 2239 1676 1137 3055 183 85 143 197 243 72 291 279 99 189 30 101 211 209 77 198 175 149 259 372 140 250 168 142 146 284 273 74 162 112 78 29 169 578 97 589 473 317 123 102 445 217 144 398 510 464 247 109 3291 216 185 1214 167 495 1859 194 1030 3456 2021 1622 3511 222 3534 1580 2066 2418 2324 93 1073 82 102 538 1552 962 91 836 1628 2154 2144 1378 149 963 1242 849 726 1158 164 1134 658 161 1148 336 826 1303 811 178 3421 1404 2360 2643 3186 3352 1112 171 168 177 146 1945 319 185 2927 2289 543 462 111 459 107 353 2006 116 2528 56 2436 1539 1770 125 2697 2432 1356 208 5013 4231 193 169 3152 2543 4430 4070 4031 145 4433 4187 4394 1754 5278 113 4427 569 5167 175 192 3903 155 1051 4121 5140 2328 203 5653 3233 how can I read it in a list of list of int in haskell? I have tried few options but I could not manage to do it. I am very new to haskell so please be patience.
First break your input into lines using lines: let test = "1 2 3 4\n 5 6 7 \n 4 2 5" let rows = lines test --literally "lines test"! Beautiful, eh? Result: ["1 2 3 4"," 5 6 7 "," 4 2 5"] :: [[Char]] Then, extract individual numbers as strings using words: let nums_as_strings = map words rows Result: [["1","2","3","4"],["5","6","7"],["4","2","5"]] :: :: [[[Char]]] The last thing to do is convert these strings to integers with read: let numbers = map (map read) nums_as_strings :: [[Int]] Result: [[1,2,3,4],[5,6,7],[4,2,5]] :: [[Int]] Or, squashed into one line: let numbers = map (map read) (map words $ lines test) :: [[Int]] Example with your data: Prelude> let test = "1224 926 1380 688 845 109 118 88 1275 1306 91 796 102 1361 27 995\n1928 2097 138 1824 198 117 1532 2000 1478 539 1982 125 1856 139 475 1338" Prelude> map (map read) (map words $ lines test) :: [[Int]] [[1224,926,1380,688,845,109,118,88,1275,1306,91,796,102,1361,27,995],[1928,2097,138,1824,198,117,1532,2000,1478,539,1982,125,1856,139,475,1338]] You may need to take care of empty lines, but that's really simple.
import System.IO readListOfLists :: Handle -> IO [[Int]] readListOfLists handle = do contents <- hGetContents handle let ls :: [String] ls = lines contents ws :: [[String]] ws= map words ls res :: [[Int]] res = map (map read) ws return res; or you can write the same code in one line: readListOfLists :: Handle -> IO [[Int]] readListOfLists = fmap (map (map read . words) . lines) . hGetContents To use it: do handle <- openFile fileName ReadMode table <- readListOfLists handle hClose handle print table
How can I replace empty cells with NA in R?
I'm new to R, and have been trying a bunch of examples but I couldn't get anything to change all of my empty cells into NA. library(XML) theurl <- "http://www.pro-football-reference.com/teams/sfo/1989.htm" table <- readHTMLTable(theurl) table Thank you.
The result you get from readHTMLTable is giving you a list of two tables, so you need to work on each list element, which can be done using lapply table <- lapply(table, function(x){ x[x == ""] <- NA return(x) }) table$team_stats Player PF Yds Ply Y/P TO FL 1stD Cmp Att Yds TD Int NY/A 1stD Att Yds TD Y/A 1stD Pen Yds 1stPy 1 Team Stats 442 6268 1021 6.1 25 14 350 339 483 4302 35 11 8.1 209 493 1966 14 4.0 124 109 922 17 2 Opp. Stats 253 4618 979 4.7 37 16 283 316 564 3235 15 21 5.3 178 372 1383 9 3.7 76 75 581 29 3 Lg Rank Offense 1 1 <NA> <NA> 2 10 1 <NA> 20 2 1 1 1 <NA> 13 10 12 13 <NA> <NA> <NA> <NA> 4 Lg Rank Defense 3 4 <NA> <NA> 11 9 9 <NA> 25 11 3 9 5 <NA> 1 3 3 8 <NA> <NA> <NA> <NA>
You have a list of data.frames of factors, though the actual data is mostly numeric. Converting to the appropriate type with type.convert will automatically insert the appropriate NAs for you: df_list <- lapply(table, function(x){ x[] <- lapply(x, function(y){type.convert(as.character(y), as.is = TRUE)}); x }) df_list[[1]][, 1:18] ## Player PF Yds Ply Y/P TO FL 1stD Cmp Att Yds.1 TD Int NY/A 1stD.1 Att.1 Yds.2 TD.1 ## 1 Team Stats 442 6268 1021 6.1 25 14 350 339 483 4302 35 11 8.1 209 493 1966 14 ## 2 Opp. Stats 253 4618 979 4.7 37 16 283 316 564 3235 15 21 5.3 178 372 1383 9 ## 3 Lg Rank Offense 1 1 NA NA 2 10 1 NA 20 2 1 1 1.0 NA 13 10 12 ## 4 Lg Rank Defense 3 4 NA NA 11 9 9 NA 25 11 3 9 5.0 NA 1 3 3 Or more concisely but with a lot of packages, library(tidyverse) # for purrr functions and readr::type_convert library(janitor) # for clean_names df_list <- map(table, ~.x %>% clean_names() %>% dmap(as.character) %>% type_convert()) df_list[[1]] ## # A tibble: 4 × 23 ## player pf yds ply y_p to fl x1std cmp att yds_2 td int ny_a ## <chr> <int> <int> <int> <dbl> <int> <int> <int> <int> <int> <int> <int> <int> <dbl> ## 1 Team Stats 442 6268 1021 6.1 25 14 350 339 483 4302 35 11 8.1 ## 2 Opp. Stats 253 4618 979 4.7 37 16 283 316 564 3235 15 21 5.3 ## 3 Lg Rank Offense 1 1 NA NA 2 10 1 NA 20 2 1 1 1.0 ## 4 Lg Rank Defense 3 4 NA NA 11 9 9 NA 25 11 3 9 5.0 ## # ... with 9 more variables: x1std_2 <int>, att_2 <int>, yds_3 <int>, td_2 <int>, y_a <dbl>, ## # x1std_3 <int>, pen <int>, yds_4 <int>, x1stpy <int>
getting a full line from unique first two columns
I have two files, and need to find the line given from a unique set of the first two columns. Essentially, I have File 1: 11 23 0.98 0.43 13 15 0.87 0.23 14 18 0.96 0.43 23 42 0.55 0.64 and File 2: 11 14 0.64 0.47 11 23 0.77 0.34 13 15 0.87 0.23 42 23 0.65 0.55 and need an output of 11 14 0.64 0.47 Most things I've seen require some form of reordering of the first two columns, which needs to be avoided. Thank you in advance!
You can use a loop for this, here is some pseudo-code: for every item x in the first column for every item y in the second column if x is equal to y then //do your stuff here
Code-golf: Output multiplication table to the Console
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions. I recently pointed a student doing work experience to an article about dumping a multiplication table to the console. It used a nested for loop and multiplied the step value of each. This looked like a .NET 2.0 approach. I was wondering, with the use of Linq and extension methods,for example, how many lines of code it would take to achieve the same result. Is the stackoverflow community up to the challenge? The challenge: In a console application, write code to generate a table like this example: 01 02 03 04 05 06 07 08 09 02 04 06 08 10 12 14 16 18 03 06 09 12 15 18 21 24 27 04 08 12 16 20 24 28 32 36 05 10 15 20 25 30 35 40 45 06 12 18 24 30 36 42 48 54 07 14 21 28 35 42 49 56 63 08 16 24 32 40 48 56 64 72 09 18 27 36 45 54 63 72 81 As this turned into a language-agnostic code-golf battle, I'll go with the communities decision about which is the best solution for the accepted answer. There's been alot of talk about the spec and the format that the table should be in, I purposefully added the 00 format but the double new-line was originally only there because I didn't know how to format the text when creating the post!
J - 8 chars - 24 chars for proper format */~1+i.9 Gives: 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81 This solution found by #earl: 'r(0)q( )3.'8!:2*/~1+i.9 Gives: 01 02 03 04 05 06 07 08 09 02 04 06 08 10 12 14 16 18 03 06 09 12 15 18 21 24 27 04 08 12 16 20 24 28 32 36 05 10 15 20 25 30 35 40 45 06 12 18 24 30 36 42 48 54 07 14 21 28 35 42 49 56 63 08 16 24 32 40 48 56 64 72 09 18 27 36 45 54 63 72 81
MATLAB - 10 characters a=1:9;a'*a ... or 33 characters for stricter output format a=1:9;disp(num2str(a'*a,'%.2d '))
Brainf**k - 185 chars >---------[++++++++++>---------[+<[-<+>>+++++++++[->+>>---------[>-<++++++++++<]<[>]>>+<<<<]>[-<+>]<---------<]<[->+<]>>>>++++[-<++++>]<[->++>+++>+++<<<]>>>[.[-]<]<]++++++++++.[-<->]<+]
cat - 252 characters 01 02 03 04 05 06 07 08 09 02 04 06 08 10 12 14 16 18 03 06 09 12 15 18 21 24 27 04 08 12 16 20 24 28 32 36 05 10 15 20 25 30 35 40 45 06 12 18 24 30 36 42 48 54 07 14 21 28 35 42 49 56 63 08 16 24 32 40 48 56 64 72 09 18 27 36 45 54 63 72 81 Assuming that a trailing newline is wanted; otherwise, 251 chars. * runs *
Python - 61 chars r=range(1,10) for y in r:print"%02d "*9%tuple(y*x for x in r)
C# This is only 2 lines. It uses lambdas not extension methods var nums = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; nums.ForEach(n => { nums.ForEach(n2 => Console.Write((n * n2).ToString("00 "))); Console.WriteLine(); }); and of course it could be done in one long unreadable line new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ForEach(n => { new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ForEach(n2 => Console.Write((n * n2).ToString("00 "))); Console.WriteLine(); }); all of this is assuming you consider a labmda one line?
K - 12 characters Let's take the rosetta-stoning seriously, and compare Kdb+'s K4 with the canonical J solution (*/~1+i.9): a*/:\:a:1+!9 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81 J's "table" operator (/) equals the K "each-left each-right" (/:\:) idiom. We don't have J's extremely handy "reflexive" operator (~) in K, so we have to pass a as both left and right argument.
Fortran95 - 40 chars (beating perl by 4 chars!) This solution does print the leading zeros as per the spec. print"(9(i3.2))",((i*j,i=1,9),j=1,9);end
Oracle SQL, 103 characters: select n, n*2, n*3, n*4, n*5, n*6, n*7, n*8, n*9 from (select rownum n from dual CONNECT BY LEVEL < 10)
C# - 117, 113, 99, 96, 95 89 characters updated based on NickLarsen's idea for(int x=0,y;++x<10;) for(y=x;y<x*10;y+=x) Console.Write(y.ToString(y<x*9?"00 ":"00 \n")); 99, 85, 82 81 characters ... If you don't care about the leading zeros and would allow tabs for alignment. for(int x=0,y;++x<10;) { var w=""; for(y=1;++y<10;) w+=x*y+" "; Console.WriteLine(w); }
COBOL - 218 chars -> 216 chars PROGRAM-ID.P.DATA DIVISION.WORKING-STORAGE SECTION. 1 I PIC 9. 1 N PIC 99. PROCEDURE DIVISION.PERFORM 9 TIMES ADD 1 TO I SET N TO I PERFORM 9 TIMES DISPLAY N' 'NO ADVANCING ADD I TO N END-PERFORM DISPLAY'' END-PERFORM. Edit 216 chars (probably a different compiler) PROGRAM-ID.P.DATA DIVISION.WORKING-STORAGE SECTION. 1 I PIC 9. 1 N PIC 99. PROCEDURE DIVISION. PERFORM B 9 TIMES STOP RUN. B. ADD 1 TO I set N to I PERFORM C 9 TIMES DISPLAY''. C. DISPLAY N" "NO ADVANCING Add I TO N.
Not really a one-liner, but the shortest linq i can think of: var r = Enumerable.Range(1, 9); foreach (var z in r.Select(n => r.Select(m => n * m)).Select(a => a.Select(b => b.ToString("00 ")))) { foreach (var q in z) Console.Write(q); Console.WriteLine(); } In response to combining this and SRuly's answer Enumberable.Range(1,9).ToList.ForEach(n => Enumberable.Range(1,9).ToList.ForEach(n2 => Console.Write((n * n2).ToString("00 "))); Console.WriteLine(); });
Ruby - 42 Chars (including one linebreak, interactive command line only) This method is two lines of input and only works in irb (because irb gives us _), but shortens the previous method by a scant 2 charcters. 1..9 _.map{|y|puts"%02d "*9%_.map{|x|x*y}} Ruby - 44 Chars (tied with perl) (a=1..9).map{|y|puts"%02d "*9%a.map{|x|x*y}} Ruby - 46 Chars 9.times{|y|puts"%02d "*9%(1..9).map{|x|x*y+x}} Ruby - 47 Chars And back to a double loop (1..9).map{|y|puts"%02d "*9%(1..9).map{|x|x*y}} Ruby - 54 chars! Using a single loop saves a couple of chars! (9..89).map{|n|print"%02d "%(n/9*(x=n%9+1))+"\n"*(x/9)} Ruby - 56 chars 9.times{|x|puts (1..9).map{|y|"%.2d"%(y+x*y)}.join(" ")}
Haskell — 85 84 79 chars r=[1..9] s x=['0'|x<=9]++show x main=mapM putStrLn[unwords[s$x*y|x<-r]|y<-r] If double spacing is required (89 81 chars), r=[1..9] s x=['0'|x<=9]++show x main=mapM putStrLn['\n':unwords[s$x*y|x<-r]|y<-r]
F# - 61 chars: for y=1 to 9 do(for x=1 to 9 do printf"%02d "(x*y));printfn"" If you prefer a more applicative/LINQ-y solution, then in 72 chars: [1..9]|>Seq.iter(fun y->[1..9]|>Seq.iter((*)y>>printf"%02d ");printfn"")
c# - 125, 123 chars (2 lines): var r=Enumerable.Range(1,9).ToList(); r.ForEach(n=>{var s="";r.ForEach(m=>s+=(n*m).ToString("00 "));Console.WriteLine(s);});
C - 97 79 characters #define f(i){int i=0;while(i++<9) main()f(x)f(y)printf("%.2d ",x*y);puts("");}}
Perl, 44 chars (No hope of coming anywhere near J, but languages with matrix ops are in a class of their own here...) for$n(1..9){printf"%3d"x9 .$/,map$n*$_,1..9}
R (very similar to Matlab on this level): 12 characters. > 1:9%*%t(1:9) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [1,] 1 2 3 4 5 6 7 8 9 [2,] 2 4 6 8 10 12 14 16 18 [3,] 3 6 9 12 15 18 21 24 27 [4,] 4 8 12 16 20 24 28 32 36 [5,] 5 10 15 20 25 30 35 40 45 [6,] 6 12 18 24 30 36 42 48 54 [7,] 7 14 21 28 35 42 49 56 63 [8,] 8 16 24 32 40 48 56 64 72 [9,] 9 18 27 36 45 54 63 72 81
PHP, 71 chars for($x=0;++$x<10;print"\n"){for($y=0;++$y<10;){printf("%02d ",$x*$y);}} Output: $ php -r 'for($x=0;++$x<10;print"\n"){for($y=0;++$y<10;){printf("%02d ",$x*$y);}}' 01 02 03 04 05 06 07 08 09 02 04 06 08 10 12 14 16 18 03 06 09 12 15 18 21 24 27 04 08 12 16 20 24 28 32 36 05 10 15 20 25 30 35 40 45 06 12 18 24 30 36 42 48 54 07 14 21 28 35 42 49 56 63 08 16 24 32 40 48 56 64 72 09 18 27 36 45 54 63 72 81
C#, 135 chars, nice and clean: var rg = Enumerable.Range(1, 9); foreach (var rc in from r in rg from c in rg select (r * c).ToString("D2") + (c == 9 ? "\n\n" : " ")) Console.Write(rc);
PostgreSQL: 81 74 chars select array(select generate_series(1,9)*x)from generate_series(1,9)as x;
Ruby - 56 chars :D 9.times{|a|9.times{|b|print"%02d "%((a+1)*(b+1))};puts;}
C - 66 Chars This resolves the complaint about the second parameter of main :) main(x){for(x=8;x++<89;)printf("%.2d%c",x/9*(x%9+1),x%9<8?32:10);} C - 77 chars Based on dreamlax's 97 char answer. His current answer somewhat resembles this one now :) Compiles ok with gcc, and main(x,y) is fair game for golf i reckon #define f(i){for(i=0;i++<9;) main(x,y)f(x)f(y)printf("%.2d ",x*y);puts("");}}
XQuery 1.0 (96 bytes) string-join(for$x in 1 to 9 return(for$y in 1 to 9 return concat(0[$x*$y<10],$x*$y,' '),' '),'') Run (with XQSharp) with: xquery table.xq !method=text
Scala - 77 59 58 chars print(1 to 9 map(p=>1 to 9 map(q=>"%02d "format(p*q))mkString)mkString("\n")) Sorry, I had to do this, the Scala solution by Malax was way too readable... [Edit] For comprehension seems to be the better choice: for(p<-1 to 9;q<-{println;1 to 9})print("%02d "format p*q) [Edit] A much longer solution, but without multiplication, and much more obfuscated: val s=(1 to 9).toSeq (s:\s){(p,q)=>println(q.map("%02d "format _)mkString) q zip(s)map(t=>t._1+t._2)}
PHP, 62 chars for(;$x++<9;print"\n",$y=0)while($y++<9)printf("%02d ",$x*$y);
Java - 155 137 chars Update 1: replaced string building by direct printing. Saved 18 chars. class M{public static void main(String[]a){for(int x,y=0,z=10;++y<z;System.out.println())for(x=0;++x<z;System.out.printf("%02d ",x*y));}} More readable format: class M{ public static void main(String[]a){ for(int x,y=0,z=10;++y<z;System.out.println()) for(x=0;++x<z;System.out.printf("%02d ",x*y)); } }
Another attempt using C#/Linq with GroupJoin: Console.Write( String.Join( Environment.NewLine, Enumerable.Range(1, 9) .GroupJoin(Enumerable.Range(1, 9), y => 0, x => 0, (y, xx) => String.Join(" ", xx.Select(x => x * y))) .ToArray()));
Ruby — 47 chars puts (a=1..9).map{|i|a.map{|j|"%2d"%(j*i)}*" "} Output 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81 (If we ignore spacing, it becomes 39: puts (a=1..9).map{|i|a.map{|j|j*i}*" "} And anyway, I feel like there's a bit of room for improvement with the wordy map stuff.)