Skip to main content

conversion - Programmatically convert notebook input cells to text file


I have ~150 student-submitted Mathematica notebooks for an assessed assignment. While I've been marking them, I'm suspecting there is a reasonable amount of plagiarism going on, when multiple students make the same odd errors throughout.


When I find something odd, I can use Notebook++ to search through all the notebooks for where it crops up elsewhere, but the .nb files have a lot of extra RowBox and BoxData etc.


I'm looking to convert just the input cells from each notebook into a text file, is there a way to do that programmatically?



The answer at: Converting a notebook to plain text programmatically shows how to automate the process of saving a single notebook as a text file, but I want just the "Input" Cells and can't figure out how to do that.


Edit:


The answer from Alexey works generally, except when an integral has been input using the Integral sign on the palette. Running the code:


name = "test2.nb"
Export["test.txt", StringJoin[
Riffle[NotebookImport[name, "Input" -> "Text"],
"\n=================\n"]], "Text", CharacterEncoding -> "PrintableASCII"]

then makes something strange happen involving a SubsuperscriptBox that I can't fix, which makes the output go over two columns, but within the text file:


Text file from the test notebook




Answer



Updated to support multiline input cells and syntax errors


I would avoid linear syntax. Why not use something like the following:


inputCellsToText[nb_, textFile_] := Internal`InheritedBlock[
{SequenceForm},
SetAttributes[SequenceForm, HoldAll];

Export[
textFile,
Flatten[extractInput /@ NotebookImport[nb, "Input"->"HeldInterpretedCell"]],

"Text"
]
]

extractInput[HoldComplete[ExpressionCell[a_List, __]]] := DeleteCases[
SequenceForm /@ Unevaluated[a],
SequenceForm[Null]
]
extractInput[HoldComplete[ExpressionCell[a_, __]]] := SequenceForm[a]


For example, the following notebook:


nb = Uncompress @"1:eJzVVc1rE0EUj7WxftBaD4onWQ9KQmrNbkIa24gkaSJVYyRbVMTLJp1tR9OZMDtrGw/iWfQqFRT8I6SXinryIChexVJQ60F6Kd48CM6bbD42TfMh9eDlzb437/P33rw9nqc50+vxeKy9glymHOUpvW3uBkm/IJewxc1dVS6JikWzD7hBhzvPqF2aNLjRZNLvMpEOBgRJ0EWp7N3qf48gObogNCoRarfS8SFBdDtv2SXErALDJS4UdbC5Oa5pWkIHH8GaQE11cCq5A4KkmVHgmBJwBybqFkNXYVLH14WOKmmgEmhIZu9KHW4rVJPU3z5hp7L0WDjpmDqCUDzURTaVGAHnu42pG6XOjsOSKg3fAR2aO0VKNq97y9lFZB10xiE5Z5BZNI3nkVWfE/CIwB5s7iRuodWljfijh5/n4KxdrCwPvVoXgsfvIq/hZM+9A2/XGzU+Dg++B8Fmjn6AsymHw+IjNV+aMyx8F+llwo3FFGOUWVJlmtmoXmTr0W05ORVEg6FksAHirM27AkHmDgrjR3/Lct/E78vqTi+dkLVMfJk4+x1qaZ+a04QdDR0bj8nQ0ku2hEh3y6DFC94e0TYPvPmVhHoZLgQa1bn4ufltBQp80Bd+udoZy96S6gXyOoCADVuO3ZD5/EuA2z7jbTdUdaYTauMK2aH1mK+t6mBUCgqVLfjX/c18+vFkTeC4ce/rs7Uu+vs/YdLTi24E5djJF08BjCNXfklQ6kPm9rNffFzDZIYu6GItuodrChKNBqPyjETPNJkO1kwzBpvFxGr1o61yOCYys/YJLm5zOm9wXHAruO+wJrgWJacZJTxFZq6K1ogFrJ8TMlUdVRWTMiVjFJSsrlxXFqMRxRfSTuUxH1EiYTiVi4gRVPQrvgsGsQ1WVsIjihZUx/xNUYah9bxcRJPIxATDmrd0QEnwhl3koyT/ByPIIdA=";

enter image description here


produces the following text file:



Integrate[1/(1 + x^2), {x, 0, Infinity}]


2 + 2


ErrorBox[ErrorBox[RowBox[{RowBox[{"4", " ", "4"}], "+"}]]]


Subscript[x, 2]^3



α^2 + (Element[b, c])



Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...