Wednesday, 21 November 2018

Go Puzzle Solutions

Sorry it took so long.  Here are the answers that everyone keeps asking for.

Please tell me if you find any mistakes.

1. c 
  
Maps are reference types to m and mcopy refer to the same map.  Since the element with an empty string as a key has been assigned to twice there are only 3 elements in the map. 
  
2. d 
  
Copy does not change the length of the destination slice; it just copies until then end of the source or destination.  In this case the source is shorter and so the subsequent previous bytes of the destination are not changed. 
  
3. c 
  
The first panic is recovered at the first recover() encountered (at line 5) which is then printed as "ABC". Then another panic occurs and is recovered by the nested defer (at line2) which is printed as "DEF". 
  
4. b 
  
The outer-scope variable c is captured in the closure passed to IndexFunc(). This contains 'c' which is matched at offset 2 in the string.  Hence IndexFunc() returns 2. 
  
5. c 
  
The string is composed of two runes of 3 bytes each.  The length of the string is the number of bytes as is the length of the slice of bytes when cast. 
  
6. a 
  
The init() functions are executed in the order they are declared so 1 then 2 are sent to then channel.  The main functions reads and prints the first value. 
  
7. c 
  
The iota has the value zero in the first line as is incremented for every subsequent line until the end of the const.  Hence the total would be 0+1+2+3. 
  
8. d 
  
The slice has length of one (2-1) and starts at index one of the array.  The copy() statement only copies to the minimum of the source and destination so only overwrites the array element at index one.  Hence the element at index 2 is unaffected. 
  
9. d 
  
The order that a map is iterated in a for-range loop is unspecified. If element 1 is seen first the first time through the loop it will be deleted and "1 1 " will be printed, then the 2nd time through the loop "2 1 " will be printed (b).  If element 2 is seen first then it will not be deleted until the 2nd time through the loop hence "2 2 1 1 " will be printed (c). 
  
10. b 
  
The variable 'b' reslices 'a' with a length of 2 (2-0) and a capacity of 4 (4-0).  The difference between capacity and length is 2. 
  
11. b 
  
There is a subtle bug that the sync.WaitGroup is passed to the closure by value.  Hence the Wait() method will never return.  You should never pass a WaitGroup by value - either capture it within the closure or pass a pointer to it. 
  
However, if this defect is fixed then the answer is d, since which go-routine proceeds after Done() is executed and Wait() can proceed is indeterminate.  It might still just print "B" is the main() function exits and the program stops before the other go-routine has a chance to print "A". 
  
12. b
  
Numeric literals have no exact type so "2e2", for example, can be assigned to an int without a cast.  However, they have a "prefered" type which is the type they take given no constraints.  Hence 'i' has type int whereas 'f' has type float64. 
  
In the 2nd line the 2nd expression is constrained to be of type float64 because of the type of 'f'.  Similarly, the 3rd expression is of type int because of the type of 'i'. 
  
The literals in the first expression in the 2nd line are unconstrained but an int (prefered type of "200") is trumped by float64 (the prefered type of "2e2"). 
  
13. a
  
The slice 's' has length 1 and capacity 2. The append statement requires a capacity of 4 so it causes a memory allocation and 't' now has a different underlying array to 's' - ie, 's' is not affected by the append.  The new slice 't' has then length and capacity(?) of one byte (from 's') and the 3 appended bytes. 
  
14. c 
  
The variable (a) is an array of 4 elements since the last index specified is 3 (idx+1). Note that the unspecified elements (with indices of 0 and 2) are initialised to zero. 
  
15. b 
  
An interface is a reference type so the variable b refers to the int a.  The answers c and d can never happen since all parameters passed to fmt.Println() are automatically cast to interface{} types and the referenced value is printed. 
  
16. c 
  
There is no initializer on the 2nd and 4th lines so the one from the line above is used. By the 3rd line iota has the value 2 and on the 4th line it's 3. Hence the answer is 0+0+2+3. 
  
17. c 
  
The first append does not require a reallocation since the slice has length 1 but capacity 2 - so 3 is placed in array element at index 1. The first append requires a reallocation so the original underlying array is not touched. 
  
18. d 
  
The type of a map key must be comparable so can't be a slice, map or function type, since these types cannot be compared (except to nil). However, map keys can be interface types whence the underlying types are compared.  But in this case the underlying type for the 2nd element added (m[b]) is a slice. Since slices cannot be compared and the type of the key is not determined until run-time then this causes a panic. 
  
19. c
  
Normally you can't modify a value returned from a map and have it reflected in the map since a copy of the map element is returned. However, in this case the map contains pointers. We don't modify the pointer but the int field of the struct pointed to is incremented from 1 to 2. 
  
20. c 
  
The closure (a) returns the year for the current time (2018 at time of writing). The call to Format() returns a string containing the current year as 2 digits ("18" at time of writing) which is then converted to an int (18).  Hence the result is 18-2018 = -2000. 
  
21. d 
  
The fallthrough statement can only be used at the end of a case.  (If it worked the answer would be a.) 
  
22. b
  
The value in a for-range loop is a copy of the slice element.  Incrementing it has no effect on the slice. 
  
23. a 
  
When you copy into a slice, no more elements than the original length of the slice are copied.  The capacity is irrelevant. 
  
24. d 
  
Whether the address of a zero-sized object is unique is explicitly not defined for the Go language. But typically this will print true or false. 
  
25. c 
  
When an interface type is used as a map key the underlying values are compared (type and value). In this case both underlying values are strings with the same value, so m[a] and m[b] refer to the same element. 
  
26. d 
  
In a type-switch the variable assigned from the interface value (in this case t) takes the type specified within the code for its case clause.  However, in this case there is a list of types (int and uint) so it cannot have a specific type and retains the interface type. (If separate case clauses were use for int and uint then the answer would be a.) 
  
27. b 
  
Casting an integer to a string creates a string with a single rune represented by the integer. In this case the Unicode value 65 is the same as the ASCII value - a capital A. 
  
28. d 
  
Array elements may be initialized by index in this way but in this case i1 and i3 have the same value.  The compile sensibly detects that the same element is being set twice and produces an error. 
  
29. a 
  
The type intA is a unique type so cannot be mixed in expressions with ints without a cast.  However, the type intB is just an alias for int so the expression int(a) | b is allowed.  Of course, the bit-wise OR operation turns of all bits. 
  
30. c 
  
There are no tricks here, except that you may not realise that you do not need to wait on the channel (return value of ctx.Done()) before getting the result from ctx.Err(). 
  
31. a 
  
Iota is zero in the first line and one in the 2nd, hence the answer is 0+0+2+3. 
  
32. d (similar to 18)
  
An interface can hold a function type (main) but comparing it to another interface causes a panic as functions cannot be compared.  (See answer 18 for more information.) 
  
33. a 
  
The string to be printed contains 2 bytes containing the letter 'A' and a byte with the hex value BC. The %q format specifier does more than place double-quotes around the output string it also escapes characters making the string suitable for inserting into Go source code.  (If %s was used instead then c would be the answer.)