Wikipedia:Reference desk/Computing

Welcome to the computing section
of the Wikipedia reference desk.
Select a section:
Want a faster answer?

Main page: Help searching Wikipedia

   

How can I get my question answered?

  • Select the section of the desk that best fits the general topic of your question (see the navigation column to the right).
  • Post your question to only one section, providing a short header that gives the topic of your question.
  • Type '~~~~' (that is, four tilde characters) at the end – this signs and dates your contribution so we know who wrote what and when.
  • Don't post personal contact information – it will be removed. Any answers will be provided here.
  • Please be as specific as possible, and include all relevant context – the usefulness of answers may depend on the context.
  • Note:
    • We don't answer (and may remove) questions that require medical diagnosis or legal advice.
    • We don't answer requests for opinions, predictions or debate.
    • We don't do your homework for you, though we'll help you past the stuck point.
    • We don't conduct original research or provide a free source of ideas, but we'll help you find information you need.



How do I answer a question?

Main page: Wikipedia:Reference desk/Guidelines

  • The best answers address the question directly, and back up facts with wikilinks and links to sources. Do not edit others' comments and do not give any medical or legal advice.
See also:


November 8

Split a string at spaces into n roughly equal-length strings

In a translation project, I would like to translate labels into many different languages. The number of rows of text in each label is fixed but the number of words (delimited by spaces) in the translation is variable. As the Python script cannot tell how wide characters are, assume that each character is the same width (monospace). Instead of linewrapping to a fixed length, I prefer to make each row approximately the same length.

Can someone please describe an algorithm (preferably in python Python 2 with standard libraries) that can split a string into n roughly equal parts at its spaces? If there are fewer than n−1 spaces, the number of rows is reduced (it doesn't hyphenate).

A naive way is to wrap the text at spaces to lines of at most ⁠string length/number of rows needed⁠ characters. That would fail with, say, "AAAAA B CCCCC DDDD". Ignoring spaces, the length is 15. For 3 rows, the ratio is 5, thus the first row output is "AAAAA". As "B CCCCC" also exceeds 5, the second row output is "B", leaving "CCCCC DDDD" on the third. It should output either "AAAAA B`CCCCC`DDDD" or "AAAAA`B CCCCC`DDDD" ("`" denote hard returns) instead.

An alternative is to brute-force all partitions and choose the one with lowest maximum row length. However, with, say, 10 words and 3 rows, one has to check 120 combinations. Is there a more efficient way?

Thanks, cmɢʟee τaʟκ (please add {{ping|cmglee}} to your reply) 13:01, 8 November 2026 (UTC)

The best partition according to some criterion can be computed in quadratic time, using dynamic programming. Think of the potential split points as nodes in a graph, including the point at the start and that at the end of the string. For the string "AA B" of 4 symbols (we treat a space as a symbol) we get something like
•A•A• •B•,
with 5 nodes. The graph is directed, with an edge running from each node to each later node. For n nodes, there are 1⁄2 n (n − 1) edges.
Each edge has a non-negative weight, representing an edge cost, and the idea is to find the cheapest path from the starting point to the end point, that is, with least total path cost. This problem is an instance of the shortest path problem in a directed graphs with nonnegative weights (reading "cost" for "length" and "cheapest" for "shortest"), but slightly simpler because the nodes are already topologically sorted. Each edge corresponds to a string segment, and the path determines a partition. A segment that is too long to fit has a very high edge cost, say +∞, so that no path will be selected with such a segment. A segment that fits precisely gets edge cost 0. A segment that fits but leaves space gets a real edge cost, depending on how much slack it leaves. One cost measure is the length s of the slack, which will tend to minimize the number of rows. Another measure is s2, which I expect to be esthetically more pleasing. A compromise between these desirable properties is obtained by adding the measures: s + s2.
Edges corresponding to segments of only blank space will be treated differently in the final phase. When turning the partition into a sequence of rows, they must be skipped. Their edge cost is 0.
The algorithm determines, from right to left, the path cost of the cheapest path from each node to the end point, labelling the node with the path cost. Let the nodes be numbered from 0 to n.
The path from node n to itself is the null path; it has path cost 0. For node i < n, each path from that node to n consists of a first edge from i to a node j < n, followed by a path from j to n. In the cheapest path from i, the path from the next node j will also be a cheapest path. So the path cost of the cheapest path from i to n is equal to
min i +1 ≤ j ≤ n edgecost(i, j) + pathcost(j).
Whenever, in a loop considering j = i + 1, j = i + 2, ..., the value of edgecost(i, j) reaches +∞, the loop can be broken prematurely, since nothing further on will be any good. This will effectively make the algorithm linear time.
After this right-to-left scan, we are positioned to determine the optimal partitioning in a left-to-right scan; the same loop can immediately produce the output.
Set i equal to 0. Then, while i < n, repeat:
Find j > i such that
edgecost(i, j) + pathcost(j) = pathcost(i).
Output segment edge(i, j), unless totally blank.
Set i equal to j.
 ​‑‑Lambiam 10:29, 9 November 2026 (UTC)
I suggest looking at the Knuth–Plass line-breaking algorithm. ~2026-46630-01 (talk) 13:40, 9 November 2026 (UTC)
The above is basically a simplified (and arguably higher-level) description of that algorithm, with the innovation of starting with a right-to-left scan.  ​‑‑Lambiam 21:18, 9 November 2026 (UTC)
Thank you very much, Lambiam. In case it's useful to anyone else, I've used dynamic programming to implement the auto-wrapping below. cmɢʟee τaʟκ (please add {{ping|cmglee}} to your reply) 12:34, 10 November 2026 (UTC)
def split_to_rows(text, n_row): ## split text to up to n_row roughly equal rows
 words  = text.split()
 n_word = len(words)
 if n_word <= n_row: return words
 i_char_breaks = [0]
 for word in words: i_char_breaks.append(i_char_breaks[-1] + len(word))
 ## segment_length returns length of words[i:j] when joined with single spaces
 def segment_length(i,j): return i_char_breaks[j] - i_char_breaks[i] + j - i - 1
 target = float(segment_length(0, n_word)) / n_row
 ## costss[k][j] = minimum cost to split the first j words into k parts
 previous_cutss = [[    None    ] * (n_word + 1) for k in range(n_row + 1)]
 costss         = [[float('inf')] * (n_word + 1) for k in range(n_row + 1)]
 costss[0][0]   = 0.0
 for   k in range(1,n_row + 1):
  for  j in range(k,n_word - (n_row - k) + 1): ## j leaves >=1 word in each part
   for i in range(k - 1,j):
    length = segment_length(i,j)
    cost   = costss[k - 1][i] + (length - target) ** 2
    if cost < costss[k][j]: (costss[k][j], previous_cutss[k][j]) = (cost, i)
 ## Reconstruct the chosen parts
 (cuts, j) = ([n_word], n_word)
 for k in range(n_row, 0, -1):
  j = previous_cutss[k][j]
  cuts.append(j)
 return [' '.join(words[cuts[-(k + 1)]:cuts[-(k + 2)]]) for k in range(n_row)]
def split_to_row(text, n_row): return CR.join(split_to_rows(text, n_row))
Sometimes, brute force is a lot less complicated:
:import textwrap
:my_text = 'asdf asdffasdf asdf asdf asdfsdfasdf asdf asdfasdfasdf asdfa asdf' * 10
:target_number_of_lines = 8
:max_width = 200
:text_list = None
:# Try wrapping with increasing widths until we get the right number of lines
:for width in range(1, max_width):
:    text_list = textwrap.wrap(my_text, width)
:    if len(text_list) <= target_number_of_lines:
:        break
:if text_list is not None:
:    print('\n'.join(text_list))
:else:
:    print(f'Text requires greater than {max_width}')
:
Alien878 (talk) 14:21, 10 November 2026 (UTC)
@Alien878: Clever idea, thanks! cmɢʟee τaʟκ (please add {{ping|cmglee}} to your reply) 02:51, 11 November 2026 (UTC)
@Alien878: Instead of 1, we can search from len(my_text - (target_number_of_lines - 1)) / target_number_of_lines. Even in the ideal case, n characters will need ⁠n/target_number_of_lines⁠ characters per line, excluding spaces. Replacing each break's space with a newline makes it ⁠n − (target_number_of_lines − 1)/target_number_of_lines⁠. cmɢʟee τaʟκ (please add {{ping|cmglee}} to your reply) 03:52, 13 November 2026 (UTC)
Resolved

November 12

Microsoft Copilot

Has anyone been trying to use Microsoft Copilot and has anyone been successful at using it until 12 November 2026 and then had it stop working and provide a blank screen? (First, I have only been using it to troubleshoot my computer systems. I am not using it to contribute to Wikipedia. I am familiar with the rules.) It stopped working for me on my desktop computer, which is running Windows 11, and is also not working on my laptop computer, which I interpret as meaning that the problem is with the code in the data centers or with access to the data centers. I have restarted Windows and that has not resolved the loss of use of Copilot. Robert McClenon (talk) 22:13, 12 November 2026 (UTC)

There has been a global outage of Microsoft services, including Copilot.Guardian-Gadfium (talk) 00:00, 13 November 2026 (UTC)
I heard that on the radio after posting this. Thank you. Robert McClenon (talk) 01:37, 13 November 2026 (UTC)yes
There is a bug in the Copilot front end, so that when I try to use Copilot, I get a blank screen, rather than an error message from the client code in my machine telling me that it cannot connect to the server. Robert McClenon (talk) 02:50, 13 November 2026 (UTC)

November 14

How to create an SVG graphical timeline that's reasonably editable?

I spent some time creating User:Lol1VNIO/Template:Touhou Project print media release timeline with WP:EasyTimeline; however, it's highly inaccessible due to its uncaring fontsize (you can't change the fontsize of labels) and lack of thumbnailing support. {{Horizontal timeline}} lacks mobile support and only works with integer values (I'd like it to work with dates, not just years).

So, one idea I have is to convert the timeline into an SVG. The issue now is that the timeline is dynamic, so the file should be editable. Either it's finding software that generates a timeline with the given data or creating an SVG template that can easily be edited.

Some considerations:

  • must handle both periods (serialization) and events (single release)
  • must handle dates, not just years
  • must support long text strings (e.g., https://hamed-ta.github.io/TimelineStudio just writes "..." if I change the line name; a pull request to fix that could also work)

~~lol1VNIO (I made a mistake? talk to me) 21:09, 14 November 2026 (UTC)

November 15