首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按时间顺序快速生成回文日期

按时间顺序快速生成回文日期
EN

Code Review用户
提问于 2020-02-25 14:18:43
回答 1查看 77关注 0票数 4

02/02/2020是一个回文日,因为读取从左到右或从右到左的日期仍指相同的日历日期。而且因为使用DD/MM/YYYY格式或MM.DD.YYYY格式并不重要,所以它被称为“通用回文日”。

没有一年可以有超过一个回文日。这一点很重要,因为我们只需考虑年份,就可以通过排序获得一个按时间顺序排列的列表。

在10000年间,我们可以用4个小数位来表示,准确地说有366个回文日。

代码语言:javascript
复制
366 is (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31)

日期和月份的每一个组合都会产生一个有效的日期。自2092年(29/02/ 2092 )和9220 (02.29.9220)都将确实是闰年以来,没有必要特别注意2月29日。希望我们还在..。

日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。

仅仅结合并不能产生按时间顺序所寻求的结果。通常,我们会从组合操作中对the输出进行排序,但我发现将the输入排序到组合部分可能要快得多。甚至比产生一个未排序的列表还要快!此外,如果对输出排序在很大程度上取决于所选排序方法的质量,则对输入进行排序不会(很大)。我的代码从来不需要排序超过31个值。

如果我能使用更多的查找表,我就可以很容易地选择不排序。查找表的问题在于知道什么时候足够了。极端是一个大的查找表,最后的结果准备就绪。它的乐趣在哪里?这并不是说我还没有研究过:用4个嵌入式查找表的214个字节替换PALINDR1.ASM_Part1中的70个代码字节将使执行时间从5.4秒缩短到3.0秒。

代码语言:javascript
复制
  5.4 µsec PALINDR1.ASM Sorted inputs
  6.9 µsec PALINDR2.ASM Unsorted
111.8 µsec PALINDR3.ASM Sorted outputs

当然,这些时间不包括int 21h DOS.PrintString调用。

代码语言:javascript
复制
; PALINDR1.ASM (c) 2020 Sep Roland
; --------------------------------
; assemble with FASM

        ORG     256

; This program lists all palindrome days according to DD/MM/YYYY
; It sorts the inputs to obtain a chronological list

; Part 1 fills 4 ordered tables with the reversed textual representations
; of months and days
        push    31 30 29 12             ; (1)
        mov     bp, 1010'1101'0101b     ; LUT DaysPerMonth (1 is 31, 0 is less)
        mov     di, T12
        mov     bx, 1
NextT:  pop     dx                      ; (1) -> DX={12,29,30,31}
        push    di                      ; (2) DI points behind a sentinel zero
        lea     cx, [bx-1]
        rep movsw                       ; Copy the mother table
        mov     cl, 10                  ; CONST
.Next:  mov     ax, bx
        div     cl
        add     ax, 3030h
        shr     bp, 1                   ; Hiding the DaysPerMonth info
        rcl     ax, 1                   ; ... in bit 0
        add     di, 2
        push    di                      ; (3)
.Sort:  mov     [di], si                ; Garbage the 1st time
        sub     di, 2
        mov     si, [di-2]              ; This could read the sentinel
        cmp     si, ax
        jg      .Sort
        mov     [di], ax
        pop     di                      ; (3)
        inc     bx
        cmp     bx, dx
        jbe     .Next
        xor     ax, ax                  ; Zero terminator on each table is at
        stosw                           ; the same time sentinel of next table
        pop     si                      ; (2) New table is mother of next table
        cmp     dx, 31
        jb      NextT

; Part 2 makes all the valid month and day combinations (366 in all)
        mov     si, T12
        lodsw
        shr     ax, 1                   ; -> CF (*) Extract DaysPerMonth info
; The outer loop updates the month and century fields
Outer:  push    si                      ; (4)
        mov     si, T12+(12+1+29+1+30+1)*2 ; Point at T31
        jc      .a                      ; (*) OK, 31 days
        sub     si, (30+1)*2            ; Point at T30
        cmp     ax, "02"                ; Is it February ?
        jne     .a                      ; No, 30 days
        sub     si, (29+1)*2            ; Point at T29, 29 days
.a:     mov     [String+3], ax          ; 2-digit month
        mov     [String+6], ah          ; 2-digit century
        mov     [String+7], al

        lodsw
        shr     ax, 1
; The inner loop updates the day and year fields
Inner:  mov     [String+0], ax          ; 2-digit day
        mov     [String+8], ah          ; 2-digit year
        mov     [String+9], al
        mov     dx, String
        mov     ah, 09h                 ; DOS.PrintString
        int     21h
        lodsw
        shr     ax, 1                   ; No info to extract, but
        jnz     Inner                   ; ... used as iterator test

        pop     si                      ; (4)
        lodsw
        shr     ax, 1                    ; -> CF (*) Extract DaysPerMonth info
        jnz     Outer

        mov     ax, 4C00h                ; DOS.Terminate
        int     21h
; --------------------------------------
String: db      '../../....', 13, 10, '作为比较,这里有未排序和后排序的DD/MM/YYYY版本:; PALINDR2.ASM (c) 2020 Sep Roland
; --------------------------------
; assemble with FASM

        ORG     256

; This program lists all palindrome days according to DD/MM/YYYY
; It does not produce a chronological list

; The code makes all the valid month and day combinations (366 in all)

        xor     si, si                  ; Month
; The outer loop updates the month and century fields
Outer:  mov     cl, [MDays+si]          ; LUT DaysPerMonth
        inc     si
        mov     ax, si
        aam
        add     ax, "00"
        mov     [String+6], ax          ; 2-digit century
        mov     [String+3], ah          ; 2-digit month
        mov     [String+4], al

        xor     di, di                  ; Day
; The inner loop updates the day and year fields
Inner:  inc     di
        mov     ax, di
        aam
        add     ax, "00"
        mov     [String+8], ax          ; 2-digit year
        mov     [String+0], ah          ; 2-digit day
        mov     [String+1], al
        mov     dx, String
        mov     ah, 09h                 ; DOS.PrintString
        int     21h

        dec     cl                      ; Next day
        jnz     Inner

        cmp     si, 12                  ; Next month
        jb      Outer

        mov     ax, 4C00h               ; DOS.Terminate
        int     21h
; --------------------------------------
String: db      '../../....', 13, 10, '; PALINDR3.ASM (c) 2020 Sep Roland
; --------------------------------
; assemble with FASM

        ORG     256

; This program lists all palindrome days according to DD/MM/YYYY
; It sorts the outputs to produce a chronological list

; Part 1 creates an ordered list of palindrome years
        xor     dx, dx                  ; Table size
        xor     si, si                  ; Month
; The outer loop inserts the reversed textual representation of the month
; as the most significant part of the 4-byte string in EBX
; e.g. for February - EBX=5048____h (EBX="__02")
Outer:  mov     cl, [MDays+si]          ; LUT DaysPerMonth
        inc     si
        mov     ax, si
        aam
        add     ax, "00"
        xchg    al, ah
        mov     bx, ax
        shl     ebx, 16

        xor     di, di                  ; Day
; The inner loop inserts the reversed textual representation of the day
; as the least significant part of the 4-byte string in EBX
; e.g. for 1 February - EBX=50484948h (EBX="0102")
Inner:  inc     di
        mov     ax, di
        aam
        add     ax, "00"
        xchg    al, ah
        mov     bx, ax

; MergeSorting EBX into the growing table
; e.g. EBX=50484948h (EBX="0102") corresponds to the year 2010
        mov     bp, dx
Look:   mov     eax, [Table+bp-4]       ; This could read the sentinel
        cmp     eax, ebx
        jb      Found
        mov     [Table+bp], eax
        sub     bp, 4
        jnz     Look
Found:  mov     [Table+bp], ebx         ; Add new element
        add     dx, 4                   ; The array grows

        dec     cl                      ; Next day
        jnz     Inner

        cmp     si, 12                  ; Next month
        jb      Outer

; Part 2 displays the whole list of completed palindrome days
        mov     si, Table
        mov     di, String
        mov     dx, di
Show:   lodsd
        mov     [di], ax                ; 2-digit day
        bswap   eax
        mov     [di+3], ah              ; \ 2-digit month
        mov     [di+4], al              ; /
        mov     [di+6], eax             ; 4-digit year
        mov     ah, 09h                 ; DOS.PrintString
        int     21h
        cmp     si, Table+366*4
        jb      Show

        mov     ax, 4C00h               ; DOS.Terminate
        int     21h
; --------------------------------------
String: db      '../../....', 13, 10, '关于MM.DD.YYYY格式的最后说明(未显示)引用一段话:日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?
        ALIGN   2
        dw      0                       ; Sentinel
T12:    rw      12+1+29+1+30+1+31+1作为比较,这里有未排序和后排序的DD/MM/YYYY版本:A5A6K17关于MM.DD.YYYY格式的最后说明(未显示)K28引用一段话:J19日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。J210这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?
MDays:  db      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31A6K17关于MM.DD.YYYY格式的最后说明(未显示)K28引用一段话:J19日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。J210这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?
        ALIGN   2
        dw      0                       ; Sentinel
T12:    rw      12+1+29+1+30+1+31+1

作为比较,这里有未排序和后排序的DD/MM/YYYY版本:

A5A6K17关于MM.DD.YYYY格式的最后说明(未显示)K28

引用一段话:

J19

日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。

J210

这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?

MDays: db 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ALIGN 4 dd 0 ; Sentinel Table: rd 366K17关于MM.DD.YYYY格式的最后说明(未显示)K28

引用一段话:

J19

日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。

J210

这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?

ALIGN 2 dw 0 ; Sentinel T12: rw 12+1+29+1+30+1+31+1

作为比较,这里有未排序和后排序的DD/MM/YYYY版本:

A5A6K17关于MM.DD.YYYY格式的最后说明(未显示)K28

引用一段话:

J19

日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。

J210

这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?

MDays: db 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31A6K17关于MM.DD.YYYY格式的最后说明(未显示)K28

引用一段话:

J19

日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。

J210

这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?

ALIGN 2 dw 0 ; Sentinel T12: rw 12+1+29+1+30+1+31+1

作为比较,这里有未排序和后排序的DD/MM/YYYY版本:

A5A6K17关于MM.DD.YYYY格式的最后说明(未显示)K28

引用一段话:

J19

日和月的组合使用嵌套循环完成。外部循环必须在一个月内迭代,因为我们只有在选择了一个月并查询了一个查找表(LUT),才能知道内环的迭代计数,以确定该月份有多少天。

J210

这个约束对于未排序和后排序的MM.DD.YYYY版本并不重要,但是对于预排序的MM.DD.YYYY版本,我看不到任何方法。有什么想法吗?

EN

回答 1

Code Review用户

回答已采纳

发布于 2020-02-28 15:29:39

这个程序根据MM.DD.YYYY.

列出所有回文天数

代码生成所有有效的月和日组合(总计366)。它使用4个预先排序的查找表(嵌入速度)来获得一个时间顺序列表.

在MM.DD.YYYY格式中,YYYY一年中最重要的部分反映在DD日。这将用于外循环。外部循环在T31列表中运行,以便处理所有可能的天数。

在MM.DD.YYYY格式中,YYYY一年中最不重要的部分反映在月份MM.中。这将用于内循环。然而,迭代次数将因日值大于(a)、等于(b)或小于(c)而变化:

(A)当外循环处理第31天时,.The内环在T7列表中运行。存储为“31”。(B)当外循环处理第30天时,.The内环在T11列表中运行。存储为“30”。(C)外部循环处理的.The内环每隔一天运行一次T12列表。

T31列表是范围内数字的两个字符ASCII表示的有序列表。T12列表是集合{1,2,3,4,5,6,7,8,9,10,11,12}中两个字符ASCII表示的有序列表。有29+日的月份。(就这个项目而言,二月有29天。)T11列表是集合{1,3,4,5,6,7,8,9,10,11,12}中两个字符ASCII表示的有序列表。有30+日的月份。T7列表是集合{1,3,5,7,8,10,12}中两个字符的ASCII表示的有序列表。有31天的月份。

代码语言:javascript
复制
        2-chars    List    List
Number   ASCII     Entry   Order
---------------------------------
   1  ->  '01' ->  3130h    4th
   2  ->  '02' ->  3230h    8th
   3  ->  '03' ->  3330h   11th

  10  ->  '10' ->  3031h    1st
  11  ->  '11' ->  3131h    5th
  12  ->  '12' ->  3231h    9th

  20  ->  '20' ->  3032h    2nd
  21  ->  '21' ->  3132h    6th
  22  ->  '22' ->  3232h   10th

  30  ->  '30' ->  3033h    3rd
  31  ->  '31' ->  3133h    7th

最终结果的时间顺序(要求数字反转)自然来自对这些基于文本的表进行排序。

代码语言:javascript
复制
  mov   si, T31
  lodsw
Outer:
  push  si
  mov   si, T7
  cmp   ax, "31"
  je    @f
  mov   si, T11
  cmp   ax, "30"
  je    @f
  mov   si, T12
@@:
  mov   [String+3], ax  ;Day
  mov   [String+6], ah  ;Century
  mov   [String+7], al
  lodsw
Inner:
  mov   [String], ax    ;Month
  mov   [String+8], ah  ;Year
  mov   [String+9], al
  mov   dx, String
  mov   ah, 09h         ;Print string
  int   21h
  lodsw
  test  ax, ax
  jnz   Inner
  pop   si
  lodsw
  test  ax, ax
  jnz   Outer

  mov   ax, 4C00h       ;Exit to DOS
  int   21h

  ALIGN 2
T7:
  db '10011203050708'
  dw 0
T11:
  db '1001111203040506070809'
  dw 0
T12:
  db '100111021203040506070809'
  dw 0
T31:
  db '10203001112131021222031323041424051525061626071727081828091929'
  dw 0
String:
  db '..........',13,10,'
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/237909

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档